import Tesseract from "tesseract.js";
const pdf = require("pdf-parse");

export interface ExtractedData {
  amount?: number;
  date?: Date;
  reference?: string;
  senderName?: string;
  senderBank?: string;
}

const patterns = {
  amount: /(?:monto|total|importe|cantidad|abono)[:\s]*[$]?\s*([\d,]+\.?\d*)/i,
  date: /(?:fecha|el)[\s:]*([\d]{1,2})[\/\-]([\d]{1,2})[\/\-]([\d]{2,4})/i,
  reference: /(?:referencia|clave|operación|folio)[:\s]*([\w\d]+)/i,
  senderName:
    /(?:de|origen|remitente|titular)[:\s]*([a-zA-ZáéíóúÁÉÍÓÚñÑ\s]+?)(?=\s*(?:cuenta|banco|fecha|monto|$))/i,
  senderBank: /(?:banco)[:\s]*([a-zA-ZáéíóúÁÉÍÓÚñÑ\s]+?)(?=\s*(?:cuenta|fecha|monto|$))/i,
};

function cleanNumber(value: string): number {
  return parseFloat(value.replace(/,/g, ""));
}

function parseDate(value: string): Date {
  const [, day, month, year] = value.match(/([\d]{1,2})[\/\-]([\d]{1,2})[\/\-]([\d]{2,4})/) || [];

  const yearNum = year?.length === 2 ? parseInt(`20${year}`) : parseInt(year || "");
  const monthNum = parseInt(month || "");
  const dayNum = parseInt(day || "");

  if (isNaN(yearNum) || isNaN(monthNum) || isNaN(dayNum)) {
    return new Date();
  }

  return new Date(yearNum, monthNum - 1, dayNum);
}

function cleanString(value: string): string {
  return value.trim().replace(/\s+/g, " ").replace(/[,.]$/g, "");
}

export async function processOCR(
  buffer: Buffer,
  fileType: string
): Promise<{
  text: string;
  extractedData: ExtractedData;
  confidence: number;
}> {
  let text = "";
  let confidence = 0;

  if (fileType === "application/pdf") {
    const data = await pdf.default(buffer);
    text = data.text;
    confidence = 0.7;
  } else if (fileType === "image/jpeg" || fileType === "image/png") {
    const result = await Tesseract.recognize(buffer, "spa", {
      logger: (m) => console.log(`[OCR] ${m.status}: ${(m.progress * 100).toFixed(0)}%`),
    });
    text = result.data.text;
    confidence = result.data.confidence;
  } else {
    throw new Error(`Unsupported file type: ${fileType}`);
  }

  console.log(`[OCR] Extracted text (${confidence.toFixed(2)}%):\n${text}\n`);

  const extractedData: ExtractedData = {};

  const amountMatch = text.match(patterns.amount);
  if (amountMatch) {
    extractedData.amount = cleanNumber(amountMatch[1]);
  }

  const dateMatch = text.match(patterns.date);
  if (dateMatch) {
    extractedData.date = parseDate(dateMatch[0]);
  }

  const referenceMatch = text.match(patterns.reference);
  if (referenceMatch) {
    extractedData.reference = cleanString(referenceMatch[1]);
  }

  const senderNameMatch = text.match(patterns.senderName);
  if (senderNameMatch) {
    extractedData.senderName = cleanString(senderNameMatch[1]);
  }

  const senderBankMatch = text.match(patterns.senderBank);
  if (senderBankMatch) {
    extractedData.senderBank = cleanString(senderBankMatch[1]);
  }

  console.log("[OCR] Extracted data:", extractedData);

  return {
    text,
    extractedData,
    confidence,
  };
}
