import { ExcelRow } from '../types'; const SUPABASE_URL = 'https://hwithddwaapyhnfwcesj.supabase.co'; const SUPABASE_KEY = 'sb_publishable_fGXkh0bSrAOqSk2jWKAzSg_NJD9YPCv'; async function fetchWithRetry( url: string, options: RequestInit, retries = 2, delayMs = 1000 ): Promise { let lastError: Error | null = null; for (let attempt = 0; attempt <= retries; attempt++) { try { const res = await fetch(url, options); if (res.ok || res.status < 500 || attempt === retries) return res; } catch (err) { lastError = err as Error; if (attempt === retries) throw lastError; } await new Promise(r => setTimeout(r, delayMs)); } throw lastError ?? new Error('fetch failed'); } export async function saveRowToSupabase(articleNo: string, rowData: ExcelRow): Promise { try { // Single upsert: POST with Prefer=resolution=merge-duplicates // This handles both INSERT (new article) and UPDATE (existing) atomically. // The old PATCH approach silently failed for new articles because Supabase // returns 200 OK with an empty body when no rows match — indistinguishable // from a successful update. const response = await fetchWithRetry(`${SUPABASE_URL}/rest/v1/products_sync`, { method: 'POST', headers: { 'apikey': SUPABASE_KEY, 'Authorization': `Bearer ${SUPABASE_KEY}`, 'Content-Type': 'application/json', 'Prefer': 'resolution=merge-duplicates' }, body: JSON.stringify({ id: articleNo, data: rowData, status_check: 'pending', updated_at: new Date().toISOString() }) }); if (!response.ok) { const errorData = await response.json().catch(() => ({})); console.error('Supabase upsert failed:', response.status, errorData); return false; } return true; } catch (error) { console.error('Error saving to Supabase:', error); return false; } } export async function getAllSyncedRows(): Promise> { try { // Explicit limit to avoid Supabase's default 1000-row cap const response = await fetch( `${SUPABASE_URL}/rest/v1/products_sync?select=id,data,status_check&limit=10000`, { headers: { 'apikey': SUPABASE_KEY, 'Authorization': `Bearer ${SUPABASE_KEY}`, 'Range': '0-9999' } } ); if (!response.ok) return {}; const data = await response.json(); const result: Record = {}; data.forEach((item: any) => { result[item.id] = { data: item.data, status: item.status_check || 'original' }; }); return result; } catch (error) { console.error('Error fetching from Supabase:', error); return {}; } } export async function resetAllPendingRows(): Promise { try { const response = await fetch(`${SUPABASE_URL}/rest/v1/products_sync?status_check=eq.pending`, { method: 'PATCH', headers: { 'apikey': SUPABASE_KEY, 'Authorization': `Bearer ${SUPABASE_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ status_check: 'original', updated_at: new Date().toISOString() }) }); return response.ok; } catch (error) { console.error('Error resetting statuses in Supabase:', error); return false; } } export interface HistoryEntry { id: string; product_id: string; article_name: string; old_data: ExcelRow; new_data: ExcelRow; changed_at: string; changed_by: string; } export async function saveHistoryEntry( articleNo: string, articleName: string, oldData: ExcelRow, newData: ExcelRow, userEmail: string ): Promise { try { const response = await fetch(`${SUPABASE_URL}/rest/v1/products_history`, { method: 'POST', headers: { 'apikey': SUPABASE_KEY, 'Authorization': `Bearer ${SUPABASE_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ product_id: articleNo, article_name: articleName, old_data: oldData, new_data: newData, changed_at: new Date().toISOString(), changed_by: userEmail }) }); return response.ok; } catch (error) { console.error('Error saving history to Supabase:', error); return false; } } export async function getHistory(): Promise { try { const response = await fetch( `${SUPABASE_URL}/rest/v1/products_history?select=*&order=changed_at.desc&limit=100`, { headers: { 'apikey': SUPABASE_KEY, 'Authorization': `Bearer ${SUPABASE_KEY}` } } ); if (!response.ok) return []; return await response.json(); } catch (error) { console.error('Error fetching history from Supabase:', error); return []; } }