import { createAi } from '../genkit';

export type InvoiceExtractionInput = {
  imageBase64?: string; // Base64-encoded image data
  imageUrl?: string; // URL to the invoice image
  transcriptText?: string; // Voice transcription or manual text
  language?: 'en' | 'ar'; // Language hint
  apiKey?: string;
};

export type ExtractedInvoiceData = {
  supplierName: string;
  supplierPhone?: string;
  supplierAddress?: string;
  invoiceNumber?: string;
  invoiceDate?: string;
  items: Array<{
    name: string;
    quantity: number;
    unitPrice: number;
    total: number;
  }>;
  invoiceTotal: number;
  taxRate?: number;
  taxAmount?: number;
  notes?: string;
  confidence: number; // 0-1 score indicating extraction confidence
};

export async function invoiceExtractionFlow(input: InvoiceExtractionInput): Promise<ExtractedInvoiceData> {
  let prompt = '';

  if (input.transcriptText) {
    prompt = `Extract purchase invoice fields from this text (language: ${input.language || 'ar'}):\n\n${input.transcriptText}\n\nReturn ONLY valid JSON with fields: supplierName, supplierPhone, supplierAddress, invoiceNumber, invoiceDate, items[{name,quantity,unitPrice,total}], invoiceTotal, taxRate, taxAmount, notes, confidence.`;
  } else if (input.imageBase64 || input.imageUrl) {
    prompt = `Analyze purchase invoice content and return ONLY valid JSON with fields: supplierName, supplierPhone, supplierAddress, invoiceNumber, invoiceDate, items[{name,quantity,unitPrice,total}], invoiceTotal, taxRate, taxAmount, notes, confidence.`;
  } else {
    throw new Error('Either imageBase64, imageUrl, or transcriptText must be provided');
  }

  try {
    const ai = createAi(input.apiKey);
    const parts: any[] = [];
    if (input.imageBase64) {
      parts.push({ media: { contentType: 'image/jpeg', url: `data:image/jpeg;base64,${input.imageBase64}` } });
    } else if (input.imageUrl) {
      parts.push({ media: { contentType: 'image/jpeg', url: input.imageUrl } });
    }
    parts.push({ text: prompt });

    const response = await ai.generate(parts as any);
    const raw = String(response?.text || '').trim();

    const fenced = raw.match(/```json\s*([\s\S]*?)```/i);
    const candidate = fenced?.[1] || raw;
    const jsonMatch = candidate.match(/\{[\s\S]*\}/);
    if (!jsonMatch) {
      throw new Error('Could not parse JSON from model response');
    }

    const extracted = JSON.parse(jsonMatch[0]) as ExtractedInvoiceData;
    return {
      supplierName: String(extracted.supplierName || '').trim() || 'Unknown Supplier',
      supplierPhone: extracted.supplierPhone ? String(extracted.supplierPhone).trim() : undefined,
      supplierAddress: extracted.supplierAddress ? String(extracted.supplierAddress).trim() : undefined,
      invoiceNumber: extracted.invoiceNumber ? String(extracted.invoiceNumber).trim() : undefined,
      invoiceDate: extracted.invoiceDate ? String(extracted.invoiceDate).trim() : undefined,
      items: Array.isArray(extracted.items)
        ? extracted.items
            .map((item) => ({
              name: String(item.name || '').trim(),
              quantity: Math.max(1, Number(item.quantity) || 1),
              unitPrice: Math.max(0, Number(item.unitPrice) || 0),
              total: Math.max(0, Number(item.total) || 0),
            }))
            .filter((item) => item.name.length > 0)
        : [],
      invoiceTotal: Math.max(0, Number(extracted.invoiceTotal) || 0),
      taxRate: extracted.taxRate !== undefined ? Math.min(1, Math.max(0, Number(extracted.taxRate) || 0)) : undefined,
      taxAmount: extracted.taxAmount !== undefined ? Math.max(0, Number(extracted.taxAmount) || 0) : undefined,
      notes: extracted.notes ? String(extracted.notes).trim() : undefined,
      confidence: Math.min(1, Math.max(0, Number(extracted.confidence) || 0.7)),
    };
  } catch (error) {
    throw new Error(`Failed to extract invoice data: ${error instanceof Error ? error.message : String(error)}`);
  }
}
