/* Data ingestion — upload, analisi AI (classifica + mappa su tabelle esistenti),
   anteprima editabile, import con relazioni, e datalake dei file caricati. */
const { useState: igus, useEffect: iguef, useRef: iguref } = React;

const CAT_META = {
  "strutturato": { label: "Strutturato", tone: "primary" },
  "semistrutturato": { label: "Semi-strutturato", tone: "warn" },
  "non-strutturato": { label: "Non strutturato", tone: "neutral" }
};

function fileToBase64(file) {
  return new Promise((resolve, reject) => {
    const r = new FileReader();
    r.onload = () => resolve(String(r.result).split(",")[1] || "");
    r.onerror = reject;
    r.readAsDataURL(file);
  });
}

function MaskIngestion() {
  const D = window.DATA;
  const [tab, setTab] = igus("importa");
  const [uploads, setUploads] = igus([]);      // { key, nome, status, file?, error? }
  const [env, setEnv] = igus(null);
  const inputRef = iguref(null);

  iguef(() => { D.api.env.get().then(setEnv).catch(() => {}); }, []);

  async function onFiles(fileList) {
    const files = Array.from(fileList || []);
    for (const f of files) {
      const key = f.name + ":" + f.size + ":" + Math.round(performance.now());
      setUploads(u => [{ key, nome: f.name, status: "analyzing" }, ...u]);
      try {
        const ext = (f.name.split(".").pop() || "").toLowerCase();
        const base64 = await fileToBase64(f);
        const res = await D.api.ingest.upload({ nome: f.name, ext, base64 });
        setUploads(u => u.map(x => x.key === key ? { ...x, status: "done", file: res.file } : x));
      } catch (e) {
        setUploads(u => u.map(x => x.key === key ? { ...x, status: "error", error: e.message } : x));
      }
    }
    if (inputRef.current) inputRef.current.value = "";
  }

  function removeUpload(key) { setUploads(u => u.filter(x => x.key !== key)); }

  return (
    <div>
      <div className="content__header">
        <div>
          <h1 className="page-title">Data ingestion</h1>
          <div className="page-sub">Carica i file: un agente li analizza, riconosce il tipo di dato e propone l'import sulle tabelle esistenti.</div>
        </div>
        <div className="anag-tabs" style={{ margin: 0 }}>
          <button className={"anag-tab " + (tab === "importa" ? "is-active" : "")} onClick={() => setTab("importa")}>Importa</button>
          <button className={"anag-tab " + (tab === "datalake" ? "is-active" : "")} onClick={() => setTab("datalake")}>Datalake</button>
        </div>
      </div>

      {tab === "importa" && (
        <div className="col" style={{ gap: 12 }}>
          {env && (
            <div className={"ingest-env " + (env.active === "demo" ? "is-demo" : "is-test")}>
              <Icon name="info" size={13} />
              I dati verranno importati nel database attivo: <strong>{env.active === "demo" ? "Dati demo" : "Database di test"}</strong>.
              {env.active === "demo" && <span> Per costruire un dataset separato, passa al «database di test» dal menu Ambiente in alto.</span>}
            </div>
          )}

          <div className="ingest-drop" onClick={() => inputRef.current && inputRef.current.click()}
            onDragOver={e => { e.preventDefault(); }}
            onDrop={e => { e.preventDefault(); onFiles(e.dataTransfer.files); }}>
            <Icon name="download" size={26} color="var(--c-primary)" />
            <div style={{ fontWeight: 600, fontSize: 13.5, marginTop: 6 }}>Trascina qui i file o clicca per selezionarli</div>
            <div className="muted" style={{ fontSize: 12 }}>CSV, Excel, JSON, XML, TXT, PDF — anche più file insieme</div>
            <input ref={inputRef} type="file" multiple style={{ display: "none" }} onChange={e => onFiles(e.target.files)} />
          </div>

          {uploads.map(u => (
            <UploadCard key={u.key} up={u} onRemove={() => removeUpload(u.key)} onImported={(file) => setUploads(arr => arr.map(x => x.key === u.key ? { ...x, file } : x))} />
          ))}
        </div>
      )}

      {tab === "datalake" && <Datalake />}
    </div>
  );
}

function UploadCard({ up, onRemove, onImported }) {
  const D = window.DATA;
  if (up.status === "analyzing") {
    return <Card><div className="row" style={{ gap: 10, padding: 6 }}><span className="spinner spinner--sm" /> <strong>{up.nome}</strong> <span className="muted">— analisi in corso…</span></div></Card>;
  }
  if (up.status === "error") {
    return <Card><div className="anag-error"><Icon name="alerts" size={13} color="#C8102E" /> {up.nome}: {up.error}</div></Card>;
  }
  const f = up.file;
  const a = f.analisi || {};
  const cat = CAT_META[a.categoria] || CAT_META["non-strutturato"];
  const [blocchi, setBlocchi] = igus(() => JSON.parse(JSON.stringify(a.blocchi || [])));
  const [busy, setBusy] = igus(false);
  const [esito, setEsito] = igus(f.esito_import || null);
  const [autoRef, setAutoRef] = igus(true);
  const [suEsistente, setSuEsistente] = igus("aggiorna");
  const compatibili = blocchi.filter(b => b.compatibile);

  function setCell(bi, ri, col, val) {
    setBlocchi(bs => bs.map((b, i) => i !== bi ? b : { ...b, righe: b.righe.map((r, j) => j !== ri ? r : { ...r, [col]: val }) }));
  }

  async function importa() {
    setBusy(true);
    try {
      const tabelle = compatibili.map(b => ({ tabella: b.tabella, righe: b.righe, marcaIntervento: b.marcaIntervento }));
      const res = await D.api.ingest.import(f.id, tabelle, { popolaAnagrafiche: autoRef, suEsistente });
      setEsito(res.file.esito_import);
      onImported(res.file);
      if (window.__maiaRefresh) window.__maiaRefresh(); // aggiorna dashboard senza ricaricare
    } catch (e) { alert("Import non riuscito: " + e.message); }
    finally { setBusy(false); }
  }

  return (
    <Card flush>
      <div className="ingest-head">
        <div>
          <div className="row" style={{ gap: 8 }}>
            <strong style={{ fontSize: 14 }}>{f.nome}</strong>
            <Pill tone={cat.tone}>{cat.label}</Pill>
            <span className="muted" style={{ fontSize: 11.5 }}>{a.formato} · {(f.size / 1024).toFixed(1)} KB</span>
            {f.stato === "imported" && <Pill tone="primary">Importato</Pill>}
          </div>
          {a.descrizione && <div className="muted" style={{ fontSize: 12, marginTop: 4, maxWidth: 640 }}>{a.descrizione}</div>}
        </div>
        <button className="btn btn--sm btn--ghost-danger" onClick={onRemove}><Icon name="close" size={12} /></button>
      </div>

      {a.duplicatoFile && (
        <div className="ingest-warn" style={{ margin: "0 16px 10px" }}>
          <Icon name="alerts" size={13} color="#C2410C" /> Questo file risulta <strong>già caricato</strong> il {new Date(a.duplicatoFile.data).toLocaleString("it-IT")} ({a.duplicatoFile.nome}). Eviti di reimportarlo.
        </div>
      )}
      {a.colonneChiave && a.colonneChiave.length > 0 && (
        <div className="ingest-rel" style={{ margin: "0 16px 8px" }}>
          <Icon name="share" size={12} color="#0E7C8C" /> <strong>Colonne-chiave rilevate:</strong> {a.colonneChiave.map(k => `${k.colonna} → ${k.riferimento}`).join(", ")}
        </div>
      )}
      {a.relazioniFile && a.relazioniFile.length > 0 && (
        <div className="ingest-rel" style={{ margin: "0 16px 10px" }}>
          <Icon name="share" size={12} color="#0E7C8C" /> <strong>Collegato ad altri file:</strong> {a.relazioniFile.map((r, i) => `${r.file} (${r.colonna} ↔ ${r.colonnaAltro}, ${r.condivisi} valori in comune)`).join("; ")}
        </div>
      )}

      <div style={{ padding: "0 16px 14px" }}>
        {!blocchi.length && <div className="muted" style={{ padding: 10 }}>Nessuna proposta di mapping.</div>}
        {blocchi.map((b, bi) => (
          <div key={bi} className="ingest-block">
            {!b.compatibile ? (
              <div className="ingest-incompat">
                <Icon name="alerts" size={14} color="#C2410C" />
                <div>
                  <strong>Entità «{b.entita}» non importabile</strong>
                  <div className="muted" style={{ fontSize: 12 }}>{b.motivo || "Nessuna tabella compatibile nel database."}</div>
                </div>
              </div>
            ) : (
              <>
                <div className="ingest-block__head">
                  <span>Entità <strong>{b.entita}</strong> → tabella <span className="mono" style={{ color: "var(--c-primary)", fontWeight: 600 }}>{b.tabella}</span></span>
                  <span className="muted" style={{ fontSize: 11.5 }}>{b.righe.length} righe</span>
                </div>
                {!!(b.campi_non_mappati || []).length && (
                  <div className="ingest-warn"><Icon name="info" size={12} color="#C2410C" /> Dati aggiuntivi non mappati (non verranno importati): <strong>{b.campi_non_mappati.join(", ")}</strong></div>
                )}
                {!!(b.relazioni || []).length && (
                  <div className="ingest-rel"><Icon name="share" size={12} color="#0E7C8C" /> Relazioni: {b.relazioni.map((r, i) => <span key={i}>{r.colonna} → {r.tabella_riferita}{i < b.relazioni.length - 1 ? "; " : ""}</span>)}</div>
                )}
                <EditableGrid colonne={b.colonne || []} righe={b.righe} onCell={(ri, col, val) => setCell(bi, ri, col, val)} />
              </>
            )}
          </div>
        ))}

        {esito && (
          <div className="ingest-esito">
            <strong>Esito import:</strong> {esito.tabelle.map((t, i) => (
              <span key={i} className="ingest-esito__t">
                {t.tabella}: <b>{t.inseriti}</b> inseriti{t.aggiornati ? <>, <b>{t.aggiornati}</b> aggiornati</> : ""}{t.saltati ? <>, {t.saltati} saltati</> : ""}{t.falliti ? <span style={{ color: "var(--c-danger)" }}>, {t.falliti} falliti</span> : ""}
              </span>
            ))}
            {esito.anagrafiche && (Object.keys(esito.anagrafiche.creati || {}).length > 0 || Object.keys(esito.anagrafiche.arricchiti || {}).length > 0) && (
              <div style={{ fontSize: 11.5, marginTop: 4, color: "#0E5A66" }}>
                <Icon name="share" size={11} color="#0E7C8C" /> Anagrafiche popolate
                {Object.keys(esito.anagrafiche.creati || {}).length > 0 && <> · create: {Object.entries(esito.anagrafiche.creati).map(([t, n]) => `${n} ${t}`).join(", ")}</>}
                {Object.keys(esito.anagrafiche.arricchiti || {}).length > 0 && <> · arricchite: {Object.entries(esito.anagrafiche.arricchiti).map(([t, n]) => `${n} ${t}`).join(", ")}</>}
              </div>
            )}
            {esito.riferimentiNonRisolti && Object.keys(esito.riferimentiNonRisolti).length > 0 && (
              <div style={{ fontSize: 11.5, marginTop: 4, color: "var(--c-text-3)" }}>
                <Icon name="info" size={11} color="#94A3B8" /> Riferimenti in attesa (si collegheranno importando la tabella relativa): {Object.entries(esito.riferimentiNonRisolti).map(([t, n]) => `${n} → ${t}`).join(", ")}.
              </div>
            )}
            {esito.tabelle.some(t => t.autofill && Object.keys(t.autofill).length) && (
              <div style={{ fontSize: 11.5, marginTop: 4, color: "#9A3412" }}>
                <Icon name="info" size={11} color="#C2410C" /> Campi obbligatori compilati con default/derivati: {esito.tabelle.filter(t => t.autofill && Object.keys(t.autofill).length).map(t => `${t.tabella} (${Object.keys(t.autofill).join(", ")})`).join("; ")}.
              </div>
            )}
            {esito.tabelle.some(t => t.saltatiDettaglio && t.saltatiDettaglio.length) && (
              <div className="muted" style={{ fontSize: 11.5, marginTop: 6 }}>
                {esito.tabelle.flatMap(t => (t.saltatiDettaglio || []).slice(0, 5).map((e, i) => <div key={"s" + t.tabella + i}>· {t.tabella} riga {e.riga} saltata: {e.motivo}</div>))}
              </div>
            )}
            {esito.tabelle.some(t => t.errori && t.errori.length) && (
              <div className="muted" style={{ fontSize: 11.5, marginTop: 6 }}>
                {esito.tabelle.flatMap(t => (t.errori || []).slice(0, 3).map((e, i) => <div key={t.tabella + i}>· {t.tabella} riga {e.riga}: {e.errore}</div>))}
              </div>
            )}
          </div>
        )}

        {!!compatibili.length && (
          <div className="row" style={{ marginTop: 12, gap: 14, flexWrap: "wrap" }}>
            <button className="btn btn--primary" onClick={importa} disabled={busy}>
              {busy ? <><span className="spinner spinner--sm" /> Import…</> : <><Icon name="check" size={12} color="white" /> Importa nel database</>}
            </button>
            <label className="ingest-toggle" title="Crea/aggiorna automaticamente pazienti, dipartimenti, DRG, chirurghi e dispositivi a partire dai dati importati (es. paziente dal codice fiscale, chirurgo dal nome)">
              <input type="checkbox" checked={autoRef} onChange={e => setAutoRef(e.target.checked)} disabled={busy} />
              Popola le anagrafiche collegate
            </label>
            <label className="ingest-toggle">
              Se il record esiste già:
              <select value={suEsistente} onChange={e => setSuEsistente(e.target.value)} disabled={busy} style={{ padding: "4px 8px", borderRadius: 6, border: "1px solid var(--c-border)", fontSize: 12 }}>
                <option value="aggiorna">Aggiorna / arricchisci (consigliato)</option>
                <option value="salta">Salta (protezione duplicati)</option>
                <option value="errore">Segnala errore</option>
              </select>
            </label>
          </div>
        )}
      </div>
    </Card>
  );
}

function EditableGrid({ colonne, righe, onCell }) {
  const LIMIT = 100;
  const shown = righe.slice(0, LIMIT);
  return (
    <div className="ingest-grid">
      <table className="table">
        <thead><tr><th style={{ width: 34 }}>#</th>{colonne.map(c => <th key={c}>{c}</th>)}</tr></thead>
        <tbody>
          {shown.map((r, ri) => (
            <tr key={ri}>
              <td className="muted tnum" style={{ fontSize: 11 }}>{ri + 1}</td>
              {colonne.map(c => (
                <td key={c} style={{ padding: 4 }}>
                  <input className="ingest-cell" value={r[c] == null ? "" : r[c]} onChange={e => onCell(ri, c, e.target.value)} />
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
      {righe.length > LIMIT && <div className="muted" style={{ fontSize: 11.5, padding: "6px 10px" }}>Mostrate {LIMIT} righe su {righe.length} (verranno importate tutte).</div>}
    </div>
  );
}

function Datalake() {
  const D = window.DATA;
  const [files, setFiles] = igus(null);
  const [sel, setSel] = igus(null);

  function load() { D.api.ingest.list().then(d => setFiles(d.files)).catch(() => setFiles([])); }
  iguef(() => { load(); }, []);

  function open(id) { D.api.ingest.get(id).then(d => setSel(d.file)); }
  async function remove(id) { if (!confirm("Eliminare il file dal datalake?")) return; await D.api.ingest.remove(id); setSel(null); load(); }

  if (sel) return <DatalakeDetail file={sel} onBack={() => setSel(null)} onRemove={() => remove(sel.id)} />;
  if (!files) return <div style={{ display: "flex", justifyContent: "center", padding: 50 }}><div className="spinner" /></div>;

  const statoPill = s => s === "imported" ? <Pill tone="primary">Importato</Pill> : s === "incompatibile" ? <Pill tone="danger">Incompatibile</Pill> : <Pill tone="warn">Analizzato</Pill>;
  return (
    <Card title="Datalake" sub={files.length + " file caricati"} flush>
      {!files.length ? <div className="muted" style={{ padding: 20, textAlign: "center" }}>Nessun file nel datalake.</div> : (
        <table className="table">
          <thead><tr><th>File</th><th>Categoria</th><th>Formato</th><th>Stato</th><th>Data</th><th style={{ width: 120 }}></th></tr></thead>
          <tbody>
            {files.map(f => (
              <tr key={f.id} className="is-clickable" onClick={() => open(f.id)}>
                <td><strong>{f.nome}</strong></td>
                <td style={{ fontSize: 12 }}>{(CAT_META[f.categoria] || {}).label || f.categoria}</td>
                <td style={{ fontSize: 12 }}>{f.formato}</td>
                <td>{statoPill(f.stato)}</td>
                <td className="tnum" style={{ fontSize: 12 }}>{new Date(f.created_at).toLocaleString("it-IT", { day: "2-digit", month: "2-digit", year: "2-digit", hour: "2-digit", minute: "2-digit" })}</td>
                <td>
                  <div className="row" style={{ gap: 4, justifyContent: "flex-end" }}>
                    <button className="btn btn--sm" onClick={e => { e.stopPropagation(); open(f.id); }}>Dettaglio</button>
                    <button className="btn btn--sm btn--ghost-danger" onClick={e => { e.stopPropagation(); remove(f.id); }}><Icon name="close" size={12} /></button>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      )}
    </Card>
  );
}

function DatalakeDetail({ file, onBack, onRemove }) {
  const a = file.analisi || {};
  const cat = CAT_META[a.categoria] || {};
  const esito = file.esito_import;
  return (
    <div className="col" style={{ gap: 12 }}>
      <div className="row" style={{ gap: 8 }}>
        <button className="btn btn--sm" onClick={onBack}><Icon name="chevron-right" size={12} /> Datalake</button>
        <button className="btn btn--sm btn--ghost-danger" onClick={onRemove}><Icon name="close" size={12} /> Elimina</button>
      </div>
      <Card>
        <div className="row" style={{ gap: 8 }}>
          <strong style={{ fontSize: 15 }}>{file.nome}</strong>
          <Pill tone={cat.tone || "neutral"}>{cat.label || a.categoria}</Pill>
          <span className="muted" style={{ fontSize: 12 }}>{a.formato} · {(file.size / 1024).toFixed(1)} KB · caricato il {new Date(file.created_at).toLocaleString("it-IT")}</span>
        </div>
        {a.descrizione && <div className="muted" style={{ fontSize: 12.5, marginTop: 6 }}>{a.descrizione}</div>}
      </Card>

      {esito ? (
        <Card title="Cosa è stato importato">
          {esito.tabelle.map((t, i) => (
            <div key={i} style={{ marginBottom: 8 }}>
              <div><strong>{t.tabella}</strong>: {t.inseriti} righe inserite{t.falliti ? <span style={{ color: "var(--c-danger)" }}>, {t.falliti} fallite</span> : ""}</div>
              {(t.errori || []).slice(0, 10).map((e, j) => <div key={j} className="muted" style={{ fontSize: 11.5 }}>· riga {e.riga}: {e.errore}</div>)}
            </div>
          ))}
        </Card>
      ) : (
        <Card title="Analisi (non ancora importato)" sub="Proposte di mapping sulle tabelle esistenti">
          {(a.blocchi || []).map((b, i) => (
            <div key={i} style={{ marginBottom: 10 }}>
              {b.compatibile
                ? <div>Entità <strong>{b.entita}</strong> → <span className="mono" style={{ color: "var(--c-primary)" }}>{b.tabella}</span> ({(b.righe || []).length} righe){(b.campi_non_mappati || []).length ? <span className="muted"> · non mappati: {b.campi_non_mappati.join(", ")}</span> : ""}</div>
                : <div style={{ color: "var(--c-warn)" }}>Entità <strong>{b.entita}</strong> non importabile — {b.motivo}</div>}
            </div>
          ))}
        </Card>
      )}
    </div>
  );
}

Object.assign(window, { MaskIngestion });
