/**
 * Utility for OFX Parsing and Text Normalization
 */

export const normalizeText = (str) => {
  if (!str) return "";
  return str
    .toLowerCase()
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "") // Remove accents
    .replace(/[^a-z0-9\s]/g, "") // Keep only alphanumeric
    .trim();
};

export const parseOFX = (ofxString) => {
  const transactions = [];
  const cleanData = ofxString.replace(/\r\n/g, "\n").replace(/\r/g, "\n");

  const trnListMatch =
    cleanData.match(/<BANKTRANLIST>([\s\S]*?)<\/BANKTRANLIST>/i) ||
    cleanData.match(/<BANKTRANLIST>([\s\S]*)/i);

  if (!trnListMatch) {
    console.error("OFX Parser: No BANKTRANLIST found.");
    return [];
  }

  const transBlock = trnListMatch[1];
  const rawTransBuffer = transBlock.split("<STMTTRN>");

  rawTransBuffer.forEach((block) => {
    if (!block.trim()) return;

    const type = extractTag(block, "TRNTYPE");
    const dateStr = extractTag(block, "DTPOSTED");
    const amountStr = extractTag(block, "TRNAMT");
    const fitId = extractTag(block, "FITID");
    const memo = extractTag(block, "MEMO");

    if (dateStr && amountStr) {
      transactions.push({
        id: fitId || `gen-${Math.random().toString(36).substr(2, 9)}`,
        date: parseOFXDate(dateStr),
        description: memo || "Sem descrição",
        normalizedDesc: normalizeText(memo || ""),
        amount: parseFloat(amountStr.replace(",", ".")),
        type: type,
        raw: block,
      });
    }
  });

  return transactions;
};

const extractTag = (block, tagName) => {
  const regex = new RegExp(`<${tagName}>([^<]+)`, "i");
  const match = block.match(regex);
  return match ? match[1].trim() : null;
};

const parseOFXDate = (dateStr) => {
  if (!dateStr || dateStr.length < 8) return new Date();
  const y = dateStr.substring(0, 4);
  const m = dateStr.substring(4, 6);
  const d = dateStr.substring(6, 8);
  return new Date(`${y}-${m}-${d}T12:00:00`);
};

export const calculateSimilarity = (str1, str2) => {
  const tokens1 = str1.split(" ");
  const tokens2 = str2.split(" ");
  let matches = 0;

  tokens1.forEach(t1 => {
    if (t1.length < 3) return; // Ignore small words
    if (tokens2.some(t2 => t2.includes(t1))) matches++;
  });

  return (matches / Math.max(tokens1.length, tokens2.length)) * 100;
};
