import type { SyncProduct } from '@/types/sync' const API_VERSION = 'v4' function normalizeHandle(ref: string): string { return ref .toLowerCase() .replace(/[^a-z0-9]+/g, '-') .replace(/^-+|-+$/g, '') } /** * Parse des lignes brutes Google Sheets en SyncProduct[]. * Colonnes : A=Référence, B=Nom, C=Description, D=Prix, E=Stock, F=Statut * Exporté pour les tests unitaires. */ export function parseSheetRows(rows: string[][]): SyncProduct[] { return rows .map((row): SyncProduct | null => { const ref = row[0]?.trim() if (!ref) return null const rawPrice = (row[3] ?? '').replace(',', '.').trim() const price = parseFloat(rawPrice || '0') return { ref, handle: normalizeHandle(ref), title: row[1]?.trim() || ref, description: row[2]?.trim() || '', price: isNaN(price) ? '0.00' : price.toFixed(2), stock: parseInt(row[4] ?? '0', 10) || 0, status: (row[5] ?? '').toLowerCase().includes('inac') ? 'draft' : 'active', } }) .filter((p): p is SyncProduct => p !== null) } /** * Lit tous les produits depuis Google Sheets via l'API v4. * Utilise un service account (GOOGLE_SERVICE_ACCOUNT_EMAIL + GOOGLE_PRIVATE_KEY). */ export async function readSheetProducts(): Promise { const email = process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL const key = process.env.GOOGLE_PRIVATE_KEY?.replace(/\\n/g, '\n') const sheetId = process.env.GOOGLE_SHEETS_ID const sheetName = process.env.GOOGLE_SHEETS_TAB ?? 'Produits' if (!email || !key || !sheetId) { throw new Error('Variables GOOGLE_SERVICE_ACCOUNT_EMAIL, GOOGLE_PRIVATE_KEY et GOOGLE_SHEETS_ID requises') } const { google } = await import('googleapis') const auth = new google.auth.GoogleAuth({ credentials: { client_email: email, private_key: key }, scopes: ['https://www.googleapis.com/auth/spreadsheets.readonly'], }) const sheets = google.sheets({ version: API_VERSION, auth }) const response = await sheets.spreadsheets.values.get({ spreadsheetId: sheetId, range: `${sheetName}!A2:F`, // A2 = skip header row }) const rows = (response.data.values ?? []) as string[][] return parseSheetRows(rows) }