// Importação de faturas de cartão: upload/colar → parse → IA categoriza → revisão → importa
const { useState: useStateFi } = React;

// ---- Parsers ----
function fatParseOFX(text) {
  const out = [];
  const blocks = text.match(/<STMTTRN>[\s\S]*?<\/STMTTRN>/gi) || [];
  for (const b of blocks) {
    const g = (tag) => { const m = b.match(new RegExp("<" + tag + ">([^<\\r\\n]+)")); return m ? m[1].trim() : ""; };
    const dt = g("DTPOSTED").slice(0, 8);
    const amt = parseFloat(g("TRNAMT").replace(",", "."));
    const desc = g("MEMO") || g("NAME") || "Lançamento";
    if (!dt || isNaN(amt)) continue;
    out.push({ date: `${dt.slice(0, 4)}-${dt.slice(4, 6)}-${dt.slice(6, 8)}`, desc, valor: Math.abs(amt), credito: amt > 0 });
  }
  return out;
}
function fatNormDate(s, year) {
  s = (s || "").trim();
  let m = s.match(/^(\d{4})-(\d{2})-(\d{2})/);
  if (m) return s.slice(0, 10);
  m = s.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})/);
  if (m) return `${m[3]}-${m[2].padStart(2, "0")}-${m[1].padStart(2, "0")}`;
  m = s.match(/^(\d{1,2})\/(\d{1,2})/);
  if (m) return `${year}-${m[2].padStart(2, "0")}-${m[1].padStart(2, "0")}`;
  return null;
}
function fatParseLinhas(text, year) {
  const out = [];
  const sep = text.includes(";") ? ";" : (text.includes("\t") ? "\t" : null);
  for (const raw of text.split(/\r?\n/)) {
    const line = raw.trim();
    if (!line) continue;
    let date = null, desc = "", valor = NaN;
    if (sep) {
      const cols = line.split(sep).map(c => c.trim().replace(/^"|"$/g, ""));
      for (const c of cols) { const d = fatNormDate(c, year); if (d) { date = d; break; } }
      // valor: última coluna numérica
      for (let i = cols.length - 1; i >= 0; i--) {
        const v = window.parseValor(cols[i]);
        if (cols[i] && !isNaN(v) && v !== 0 && !fatNormDate(cols[i], year)) { valor = v; break; }
      }
      desc = cols.filter(c => c && !fatNormDate(c, year) && String(window.parseValor(c)) !== String(valor)).sort((a, b) => b.length - a.length)[0] || "";
    } else {
      const dm = line.match(/^(\d{1,2}\/\d{1,2}(\/\d{4})?|\d{4}-\d{2}-\d{2})\s+/);
      const vm = line.match(/(-?\s?R?\$?\s?[\d.,]+)\s*$/);
      if (!vm) continue;
      valor = window.parseValor(vm[1]);
      date = dm ? fatNormDate(dm[1], year) : null;
      desc = line.slice(dm ? dm[0].length : 0, vm.index).trim();
    }
    if (!desc || isNaN(valor) || valor === 0) continue;
    out.push({ date, desc, valor: Math.abs(valor), credito: valor < 0 });
  }
  return out;
}
function fatParse(text, year) {
  if (/<OFX>|<STMTTRN>/i.test(text)) return fatParseOFX(text);
  return fatParseLinhas(text, year);
}

// ---- Heurística de categoria (fallback e pré-classificação) ----
const FAT_REGRAS = [
  [/mercado|super|carrefour|pao de acucar|extra|atacad|hortifruti|sacolao|zaffari|assai/i, "🛒 Mercado"],
  [/uber|99 ?(app|pop)?|taxi|posto|combust|estacion|ipva|pedagio|sem parar|shell|ipiranga|petrobras/i, "🚗 Transporte"],
  [/ifood|rappi|restaurante|lanche|pizza|burger|hamburg|padaria|cafe|bar |sushi|churras/i, "🍽️ Comida fora"],
  [/farmacia|drogaria|droga ?raia|pacheco|panvel|clinica|laborat|exame|medic|hospital|dentista|unimed|amil/i, "💊 Saúde"],
  [/netflix|spotify|prime|disney|hbo|max |globoplay|youtube|apple.com|icloud|google (one|storage)|assinatura|deezer|paramount/i, "📺 Assinaturas"],
  [/academia|smart ?fit|gympass|wellhub|crossfit|pilates|personal/i, "💪 Fitness"],
  [/escola|colegio|faculdade|curso|udemy|alura|kumon|wizard|cultura inglesa/i, "🎓 Educação"],
  [/petshop|petz|cobasi|veterinar|racao|pet /i, "🐶 Pet"],
  [/renner|zara|c&a|riachuelo|shein|nike|adidas|calcad|vestuar|hering/i, "👚 Roupas"],
  [/salao|cabele|barbear|manicure|estetica|sephora|boticario|natura/i, "💅 Beleza"],
  [/cinema|teatro|show|ingresso|viagem|hotel|airbnb|booking|latam|gol |azul |decolar|parque/i, "🏖️ Lazer"],
  [/presente|gift/i, "🎁 Presente"],
  [/luz|enel|energia|agua |sabesp|gas |internet|vivo|claro|tim |oi |condominio|aluguel|iptu/i, "🏠 Moradia"],
  [/brinquedo|fralda|bebe|infantil|ri happy/i, "👨‍👩‍👧‍👦 Crianças"],
  [/seguro|previdencia|porto seguro|allianz|bradesco seguros/i, "🛡️ Proteção"],
  [/doacao|dizimo|igreja|caridade/i, "🙏 Caridade"],
  [/corretora|tesouro|cdb|fundo|acoes|invest/i, "📈 Investimento"],
];
function fatCategoriaHeuristica(desc) {
  for (const [re, cat] of FAT_REGRAS) if (re.test(desc)) return cat;
  return "🤷 Outros";
}

// ---- PDF: extração de texto via pdf.js (carregado sob demanda) ----
let fatPdfjsPromise = null;
function fatLoadPdfjs() {
  if (window.pdfjsLib) return Promise.resolve(window.pdfjsLib);
  if (!fatPdfjsPromise) fatPdfjsPromise = new Promise((res, rej) => {
    const s = document.createElement("script");
    s.src = "https://unpkg.com/pdfjs-dist@3.11.174/build/pdf.min.js";
    s.onload = () => { window.pdfjsLib.GlobalWorkerOptions.workerSrc = "https://unpkg.com/pdfjs-dist@3.11.174/build/pdf.worker.min.js"; res(window.pdfjsLib); };
    s.onerror = () => { fatPdfjsPromise = null; rej(new Error("pdfjs")); };
    document.head.appendChild(s);
  });
  return fatPdfjsPromise;
}
async function fatPdfToText(buf) {
  const pdfjs = await fatLoadPdfjs();
  const doc = await pdfjs.getDocument({ data: buf }).promise;
  const linhas = [];
  for (let p = 1; p <= doc.numPages; p++) {
    const page = await doc.getPage(p);
    const tc = await page.getTextContent();
    const rows = {};
    for (const it of tc.items) {
      if (!it.str || !it.str.trim()) continue;
      const y = Math.round(it.transform[5] / 2) * 2; // agrupa itens da mesma linha
      (rows[y] = rows[y] || []).push({ x: it.transform[4], str: it.str });
    }
    const ys = Object.keys(rows).map(Number).sort((a, b) => b - a);
    for (const y of ys) linhas.push(rows[y].sort((a, b) => a.x - b.x).map(i => i.str).join(" ").replace(/\s+/g, " ").trim());
  }
  return linhas.join("\n");
}

function FaturaImport({ contas, categorias, month, year, txsExistentes, onImport }) {
  const [conta, setConta] = useStateFi(contas[0] || "XP");
  const [texto, setTexto] = useStateFi("");
  const [itens, setItens] = useStateFi(null); // [{date, desc, valor, categoria, classe, incluir, dup, ia}]
  const [fase, setFase] = useStateFi("entrada"); // entrada | analisando | revisao
  const [erro, setErro] = useStateFi(null);
  const [arquivos, setArquivos] = useStateFi([]); // [{nome, texto}]
  const [drag, setDrag] = useStateFi(false);
  const fmt = window.fmtBRLString;
  const catNomes = categorias.filter(c => c.tipo !== "Receita").map(c => c.nome);
  const mesLabel = window.MESES_FULL[month] + "/" + year;
  const defaultDate = `${year}-${String(month + 1).padStart(2, "0")}-15`;

  function addArquivo(nome, textoArq) {
    setArquivos(arr => arr.some(a => a.nome === nome) ? arr : [...arr, { nome, texto: textoArq }]);
  }
  function lerArquivos(files) {
    for (const file of Array.from(files || [])) {
      if (/\.pdf$/i.test(file.name) || file.type === "application/pdf") {
        const r = new FileReader();
        r.onload = async () => {
          try {
            const txt = await fatPdfToText(new Uint8Array(r.result));
            if (txt.trim()) addArquivo(file.name, txt);
            else setErro(`"${file.name}": PDF sem texto extraível (provavelmente escaneado). Cole as linhas da fatura manualmente.`);
          } catch (e) {
            setErro(`Não consegui ler "${file.name}". Tente exportar a fatura em OFX/CSV ou colar o texto.`);
          }
        };
        r.readAsArrayBuffer(file);
        continue;
      }
      const r = new FileReader();
      r.onload = () => addArquivo(file.name, String(r.result || ""));
      r.readAsText(file);
    }
  }
  function onDrop(e) {
    e.preventDefault(); e.stopPropagation(); setDrag(false);
    if (fase === "revisao") return;
    lerArquivos(e.dataTransfer.files);
  }

  async function analisar() {
    setErro(null);
    const fontes = [...arquivos.map(a => a.texto), texto].filter(t => t && t.trim());
    const parsed = fontes.flatMap(t => fatParse(t, year)).filter(x => !x.credito);
    if (!parsed.length) { setErro("Não reconheci lançamentos. Formatos aceitos: OFX, CSV (data; descrição; valor) ou linhas \"05/07 Descrição 123,45\"."); return; }
    setFase("analisando");
    let base = parsed.map(p => ({
      ...p,
      date: p.date || defaultDate,
      categoria: fatCategoriaHeuristica(p.desc),
      ia: false,
      incluir: true,
    }));
    // Check IA: pede a categoria correta de cada despesa
    try {
      const lista = base.map((x, i) => ({ i, descricao: x.desc, valor: x.valor }));
      const prompt = `Você é um assistente financeiro. Classifique cada despesa de fatura de cartão na categoria correta.\nCategorias válidas (use EXATAMENTE estas strings): ${JSON.stringify(catNomes)}\nDespesas:\n${JSON.stringify(lista)}\nRetorne SOMENTE um JSON array: [{"i":0,"categoria":"..."}] — uma entrada por despesa, sem texto extra.`;
      const res = await window.claude.complete(prompt);
      const m = res.match(/\[[\s\S]*\]/);
      if (m) {
        const cls = JSON.parse(m[0]);
        for (const c of cls) {
          if (base[c.i] && catNomes.includes(c.categoria)) { base[c.i].categoria = c.categoria; base[c.i].ia = true; }
        }
      }
    } catch (e) { /* mantém heurística */ }
    // Duplicatas: mesma conta, valor e data já lançados
    const chaves = new Set(txsExistentes.map(t => `${t.account}|${t.date}|${Number(t.amount).toFixed(2)}`));
    base = base.map(x => ({ ...x, dup: chaves.has(`${conta}|${x.date}|${x.valor.toFixed(2)}`), incluir: !chaves.has(`${conta}|${x.date}|${x.valor.toFixed(2)}`) }));
    setItens(base);
    setFase("revisao");
  }

  function setItem(i, patch) { setItens(arr => arr.map((x, idx) => idx === i ? { ...x, ...patch } : x)); }

  function importar() {
    const tipoDe = (cat) => (categorias.find(c => c.nome === cat) || {}).tipo || "";
    const sel = itens.filter(x => x.incluir);
    onImport(sel.map(x => ({
      id: window.uid(),
      date: x.date,
      description: x.desc,
      account: conta,
      category: x.categoria,
      type: "Despesa",
      amount: x.valor,
      status: "Pago",
      origem: "fatura",
      fixa: false,
      redutivel: tipoDe(x.categoria) === "Não Essencial",
      aggregate: false,
    })));
    setItens(null); setTexto(""); setArquivos([]); setFase("entrada");
  }

  const nIA = itens ? itens.filter(x => x.ia).length : 0;
  const nDup = itens ? itens.filter(x => x.dup).length : 0;
  const totalSel = itens ? itens.filter(x => x.incluir).reduce((s, x) => s + x.valor, 0) : 0;

  return (
    <div className={`card fat-card ${drag ? "fat-dragover" : ""}`} data-screen-label="Importar fatura"
      onDragOver={e => { e.preventDefault(); if (fase !== "revisao") setDrag(true); }}
      onDragLeave={e => { if (!e.currentTarget.contains(e.relatedTarget)) setDrag(false); }}
      onDrop={onDrop}>
      {drag && <div className="fat-drop-overlay">⬇️ Solte as faturas aqui</div>}
      <div className="card-head">
        <h3>📥 Importar fatura</h3>
        <span className="page-hint">Envie a fatura (PDF, OFX, CSV ou texto) — cada despesa passa por um check de categoria antes de entrar em {mesLabel}.</span>
      </div>

      {fase !== "revisao" && (
        <div className="fat-entrada">
          <div className="form-row">
            <div className="field"><label>Cartão</label>
              <select value={conta} onChange={e => setConta(e.target.value)}>{contas.map(c => <option key={c}>{c}</option>)}</select>
            </div>
            <div className="field"><label>Arquivos da fatura (.pdf, .ofx, .csv, .txt) — vários de uma vez, ou arraste para este card</label>
              <input type="file" multiple accept=".pdf,.ofx,.csv,.txt,.tsv" onChange={e => { lerArquivos(e.target.files); e.target.value = ""; }}/>
            </div>
          </div>
          {arquivos.length > 0 && (
            <div className="fat-chips">
              {arquivos.map(a => (
                <span className="fat-chip" key={a.nome}>📄 {a.nome}
                  <button type="button" title="Remover" onClick={() => setArquivos(arr => arr.filter(x => x.nome !== a.nome))}>✕</button>
                </span>
              ))}
            </div>
          )}
          <div className="field"><label>…ou cole as linhas da fatura</label>
            <textarea rows="5" value={texto} placeholder={"05/07 IFOOD *RESTAURANTE 89,90\n07/07 POSTO SHELL 250,00\n10/07 NETFLIX.COM 55,90"} onChange={e => setTexto(e.target.value)}></textarea>
          </div>
          {erro && <div className="fat-erro">⚠️ {erro}</div>}
          <div className="form-actions">
            <button className="btn-green" disabled={(!texto.trim() && arquivos.length === 0) || fase === "analisando"} onClick={analisar}>
              {fase === "analisando" ? "🤖 Analisando categorias…" : `Analisar ${arquivos.length > 1 ? arquivos.length + " faturas" : "fatura"} →`}
            </button>
          </div>
        </div>
      )}

      {fase === "revisao" && itens && (
        <div className="fat-revisao">
          <div className="fat-status">
            <span>✓ {itens.length} despesas reconhecidas</span>
            <span>{nIA > 0 ? `🤖 ${nIA} categorizadas por IA` : "🔎 categorias sugeridas por regras"}</span>
            {nDup > 0 && <span className="fat-dup-flag">⚠️ {nDup} possíveis duplicatas (desmarcadas)</span>}
          </div>
          <table className="rel-table fat-table">
            <thead><tr><th></th><th>Data</th><th>Descrição</th><th>Categoria (check)</th><th>Valor</th></tr></thead>
            <tbody>
              {itens.map((x, i) => (
                <tr key={i} className={!x.incluir ? "fat-off" : ""}>
                  <td><input type="checkbox" checked={x.incluir} onChange={e => setItem(i, { incluir: e.target.checked })}/></td>
                  <td><input type="date" className="fat-date" value={x.date} onChange={e => setItem(i, { date: e.target.value })}/></td>
                  <td>{x.desc}{x.dup && <em className="fat-dup"> · já lançada?</em>}</td>
                  <td>
                    <select value={x.categoria} onChange={e => setItem(i, { categoria: e.target.value })}>
                      {catNomes.map(c => <option key={c}>{c}</option>)}
                    </select>
                  </td>
                  <td className="num">{fmt(x.valor)}</td>
                </tr>
              ))}
            </tbody>
          </table>
          <div className="fat-foot">
            <button className="btn-ghost" onClick={() => { setFase("entrada"); setItens(null); }}>← Voltar</button>
            <div className="fat-foot-right">
              <span>Total a importar: <strong>{fmt(totalSel)}</strong> no cartão <strong>{conta}</strong></span>
              <button className="btn-green" disabled={!itens.some(x => x.incluir)} onClick={importar}>Importar {itens.filter(x => x.incluir).length} despesas</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { FaturaImport });
