export type QuoteExtraction = {
  insurer: string;
  formula: string;
  monthly: string;
  annual: string;
  validUntil: string;
  reference: string;
  missing: string[];
};

const insurerPatterns: Array<[RegExp, string]> = [
  [/\bAXA(?:\s+FRANCE)?\b/i, "AXA France"],
  [/\bALLIANZ\b/i, "Allianz"],
  [/\bGENERALI\b/i, "Generali"],
  [/\bABEILLE\s+ASSURANCES?\b/i, "Abeille Assurances"],
  [/\bGROUPAMA\b/i, "Groupama"],
  [/\bMMA\b/i, "MMA"],
  [/\bMAIF\b/i, "MAIF"],
  [/\bMACIF\b/i, "MACIF"],
  [/\bMATMUT\b/i, "Matmut"],
  [/\bGMF\b/i, "GMF"],
];

const formulaPatterns: Array<[RegExp, string]> = [
  [/\btous\s+risques?\s+[ée]tendue?\b/i, "Tous risques Étendue"],
  [/\btous\s+risques?\s+essentielle?\b/i, "Tous risques Essentielle"],
  [/\btous\s+risques?\b/i, "Tous risques"],
  [/\btiers\s+[ée]tendue?\b/i, "Tiers Étendue"],
  [/\btiers\s+essentielle?\b/i, "Tiers Essentielle"],
  [/\btiers\s+mini\b/i, "Tiers Mini"],
  [/\btiers\s+collision\b/i, "Tiers Collision"],
  [/\btiers\b/i, "Tiers"],
];

function cleanText(value: string) {
  return value.replace(/\u00a0/g, " ").replace(/[ \t]+/g, " ").replace(/\s*\n\s*/g, "\n").trim();
}

function amount(value?: string) {
  if (!value) return "";
  const normalized = value.replace(/\s/g, "").replace(",", ".");
  const parsed = Number(normalized);
  return Number.isFinite(parsed) && parsed > 0 ? parsed.toFixed(2) : "";
}

function firstAmount(text: string, patterns: RegExp[]) {
  for (const pattern of patterns) {
    const match = text.match(pattern);
    const parsed = amount(match?.[1]);
    if (parsed) return parsed;
  }
  return "";
}

function isoDate(value?: string) {
  if (!value) return "";
  const parts = value.match(/(\d{1,2})[/.\-](\d{1,2})[/.\-](\d{4})/);
  if (!parts) return "";
  const day = Number(parts[1]);
  const month = Number(parts[2]);
  if (day < 1 || day > 31 || month < 1 || month > 12) return "";
  return `${parts[3]}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
}

export function parseQuoteText(rawText: string, fileName = ""): QuoteExtraction {
  const text = cleanText(`${fileName}\n${rawText}`);
  const insurer = insurerPatterns.find(([pattern]) => pattern.test(text))?.[1] || "";
  const formula = formulaPatterns.find(([pattern]) => pattern.test(text))?.[1] || "";

  const monthly = firstAmount(text, [
    /(?:cotisation|prime|tarif)[^\n€]{0,45}(?:mensuelle|par mois)[^\d]{0,15}([\d\s]+[,.]\d{2})\s*€/i,
    /([\d\s]+[,.]\d{2})\s*€\s*(?:\/\s*mois|par mois|mensuels?)/i,
    /(?:mensuelle|par mois)[^\d]{0,20}([\d\s]+[,.]\d{2})\s*€/i,
    /(?:tiers\s+(?:mini|essentielle|[ée]tendue)|tous\s+risques?(?:\s+(?:essentielle|[ée]tendue))?)[^\d\n]{0,12}([\d\s]+[,.]\d{2})\s*€/i,
  ]);

  const annual = firstAmount(text, [
    /(?:cotisation|prime|tarif)[^\n€]{0,45}(?:annuelle|par an)[^\d]{0,15}([\d\s]+[,.]\d{2})\s*€/i,
    /([\d\s]+[,.]\d{2})\s*€\s*(?:\/\s*an|par an|annuels?)/i,
    /(?:annuelle|par an)[^\d]{0,20}([\d\s]+[,.]\d{2})\s*€/i,
    /(?:montant|total)[^\n€]{0,30}(?:annuel|cotisation)[^\d]{0,15}([\d\s]+[,.]\d{2})\s*€/i,
  ]);

  const validityMatch = text.match(/(?:valable\s+jusqu(?:'|’|\s+)au|validit[ée](?:\s+du\s+devis)?|date\s+limite)[^\d]{0,25}(\d{1,2}[/.\-]\d{1,2}[/.\-]\d{4})/i);
  const validUntil = isoDate(validityMatch?.[1]);
  const fields: Array<[keyof Omit<QuoteExtraction, "missing">, string]> = [
    ["insurer", "assureur"], ["formula", "formule"], ["monthly", "cotisation mensuelle"],
    ["annual", "cotisation annuelle"],
  ];
  const reference = rawText.match(/(?:r[ée]f[ée]rence\s+(?:du\s+)?(?:devis|projet)|(?:devis|projet)\s+n[°oº])\s*[:\-]?\s*([A-Z0-9][A-Z0-9-]{5,30})/i)?.[1] || "";
  const values = { insurer, formula, monthly, annual, validUntil, reference };
  return { ...values, missing: fields.filter(([key]) => !values[key]).map(([, label]) => label) };
}

export async function extractQuoteFromFile(file: File) {
  const pdfjs = await import("pdfjs-dist/legacy/build/pdf.mjs");
  pdfjs.GlobalWorkerOptions.workerSrc = new URL(
    "pdfjs-dist/legacy/build/pdf.worker.min.mjs",
    import.meta.url,
  ).toString();
  const bytes = new Uint8Array(await file.arrayBuffer());
  const pdf = await pdfjs.getDocument({ data: bytes }).promise;
  const pages: string[] = [];
  for (let pageNumber = 1; pageNumber <= pdf.numPages; pageNumber += 1) {
    const page = await pdf.getPage(pageNumber);
    const content = await page.getTextContent();
    pages.push(content.items.map((item) => ("str" in item ? item.str : "")).join(" "));
  }
  const text = pages.join("\n");
  return { text, extracted: parseQuoteText(text, file.name) };
}
