// ============================================================
// Audit.jsx — FASE 17-18 Audit UI dedicata
// ============================================================
// Fetch live da /api/audit-log con filtri (actor, entityType, action,
// date range), paginazione server-side, drill-down modal con diff.
function Audit() {
  const { seed } = useStore();
  const personas = (seed && seed.PERSONAS) || [];

  // Filtri
  const [filterActor, setFilterActor] = React.useState('');
  const [filterEntityType, setFilterEntityType] = React.useState('');
  const [filterEntityId, setFilterEntityId] = React.useState('');
  const [filterAction, setFilterAction] = React.useState('');
  const [filterFrom, setFilterFrom] = React.useState('');
  const [filterTo, setFilterTo] = React.useState('');

  // Paginazione
  const [pageSize, setPageSize] = React.useState(50);
  const [page, setPage] = React.useState(1);

  const [data, setData] = React.useState([]);
  const [total, setTotal] = React.useState(0);
  const [kpi, setKpi] = React.useState({ total: 0, last30d: 0, last24h: 0, distinctActors30d: 0 });
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState(null);
  const [sel, setSel] = React.useState(null);

  // Builder URL
  const url = React.useMemo(() => {
    const p = new URLSearchParams();
    p.set('limit', String(pageSize));
    p.set('offset', String((page - 1) * pageSize));
    if (filterActor) p.set('actorPersonaId', filterActor);
    if (filterEntityType) p.set('entityType', filterEntityType);
    if (filterEntityId) p.set('entityId', filterEntityId);
    if (filterAction) p.set('action', filterAction);
    if (filterFrom) p.set('from', new Date(filterFrom + 'T00:00:00Z').toISOString());
    if (filterTo) p.set('to', new Date(filterTo + 'T23:59:59Z').toISOString());
    return `/api/audit-log?${p.toString()}`;
  }, [pageSize, page, filterActor, filterEntityType, filterEntityId, filterAction, filterFrom, filterTo]);

  React.useEffect(() => {
    let cancelled = false;
    setLoading(true);
    setError(null);
    fetch(url)
      .then(r => r.json())
      .then(json => {
        if (cancelled) return;
        if (json.error) {
          setError(json.error);
          setData([]);
          setTotal(0);
          return;
        }
        setData(json.data || []);
        setTotal(json.total || 0);
        setKpi(json.kpi || { total: 0, last30d: 0, last24h: 0, distinctActors30d: 0 });
      })
      .catch(e => { if (!cancelled) setError(String(e?.message || e)); })
      .finally(() => { if (!cancelled) setLoading(false); });
    return () => { cancelled = true; };
  }, [url]);

  // Quando i filtri cambiano, torno a pagina 1
  React.useEffect(() => { setPage(1); }, [filterActor, filterEntityType, filterEntityId, filterAction, filterFrom, filterTo, pageSize]);

  const totalPages = Math.max(1, Math.ceil(total / pageSize));
  const personaName = (id) => personas.find(p => p.id === id)?.name || id || 'sistema';

  // Distinct entity types (dai dati visibili — euristica)
  const entityTypeOptions = React.useMemo(() => {
    const known = ['project','rda','vendor','communication','approval_workflow','approval_matrix','sla_policy','escalation_rule','notification_rule','notification_event','category','doc_type','site','calendar','legal_entity','business_unit','role','delegation','clause','template','branding','config_version','project_milestone','project_document','signature_request'];
    const set = new Set([...known, ...data.map(r => r.entityType)]);
    return [...set].filter(Boolean).sort();
  }, [data]);

  const actionOptions = ['create', 'update', 'delete', 'publish', 'login', 'export'];

  function clearFilters() {
    setFilterActor(''); setFilterEntityType(''); setFilterEntityId('');
    setFilterAction(''); setFilterFrom(''); setFilterTo('');
  }

  return (
    <div className="page fade-in">
      <div className="page-header">
        <div>
          <div className="eyebrow">Governance · compliance</div>
          <h1 className="page-title">Audit trail</h1>
          <div className="page-sub">
            Stream eventi audit_log: ogni mutazione del dominio e della config registra attore, timestamp, diff prima/dopo, hash chain. Filtra e drill-down per ispezione compliance.
          </div>
        </div>
        <div className="actions">
          <Btn variant="ghost" size="sm"><Icon name="download" size={12}/> Export CSV</Btn>
        </div>
      </div>

      <div className="grid grid-4" style={{marginBottom: 14}}>
        <div className="card"><Stat label="Eventi totali" value={kpi.total.toLocaleString('it-IT')} delta={`${kpi.last30d.toLocaleString('it-IT')} ultimi 30gg`} /></div>
        <div className="card"><Stat label="Eventi 24h" value={kpi.last24h.toLocaleString('it-IT')} delta={kpi.last24h > 0 ? 'attività recente' : 'nessuna attività'} tone={kpi.last24h > 0 ? 'up' : ''} /></div>
        <div className="card"><Stat label="Attori distinti (30gg)" value={kpi.distinctActors30d} delta="utenti + sistema" /></div>
        <div className="card"><Stat label="Match query corrente" value={total.toLocaleString('it-IT')} delta={loading ? 'caricamento…' : `pagina ${page} di ${totalPages}`} tone={total > 0 ? '' : 'down'} /></div>
      </div>

      {/* Filtri */}
      <div className="card" style={{marginBottom: 14}}>
        <div className="card-body" style={{padding: 12}}>
          <div className="row" style={{gap: 8, alignItems: 'flex-end', flexWrap: 'wrap'}}>
            <div className="field" style={{flex: '0 0 180px'}}>
              <label style={{fontSize: 10}}>Attore</label>
              <select value={filterActor} onChange={e => setFilterActor(e.target.value)}>
                <option value="">— tutti —</option>
                {personas.map(p => <option key={p.id} value={p.id}>{p.name}</option>)}
              </select>
            </div>
            <div className="field" style={{flex: '0 0 200px'}}>
              <label style={{fontSize: 10}}>Tipo entità</label>
              <select value={filterEntityType} onChange={e => setFilterEntityType(e.target.value)}>
                <option value="">— tutti —</option>
                {entityTypeOptions.map(t => <option key={t} value={t}>{t}</option>)}
              </select>
            </div>
            <div className="field" style={{flex: '0 0 200px'}}>
              <label style={{fontSize: 10}}>ID entità</label>
              <input value={filterEntityId} onChange={e => setFilterEntityId(e.target.value)} placeholder="es. WF_RDA_FAST" style={{fontFamily: 'var(--font-mono)', fontSize: 11}}/>
            </div>
            <div className="field" style={{flex: '0 0 130px'}}>
              <label style={{fontSize: 10}}>Azione</label>
              <select value={filterAction} onChange={e => setFilterAction(e.target.value)}>
                <option value="">— tutte —</option>
                {actionOptions.map(a => <option key={a} value={a}>{a}</option>)}
              </select>
            </div>
            <div className="field" style={{flex: '0 0 140px'}}>
              <label style={{fontSize: 10}}>Da data</label>
              <input type="date" value={filterFrom} onChange={e => setFilterFrom(e.target.value)}/>
            </div>
            <div className="field" style={{flex: '0 0 140px'}}>
              <label style={{fontSize: 10}}>A data</label>
              <input type="date" value={filterTo} onChange={e => setFilterTo(e.target.value)}/>
            </div>
            <Btn variant="ghost" size="sm" onClick={clearFilters}><Icon name="x" size={11}/> Reset</Btn>
          </div>
        </div>
      </div>

      {error && (
        <div style={{ marginBottom: 14, padding: '10px 12px', border:'1px solid var(--err)', borderRadius:6, background:'rgba(192,57,43,0.08)', color:'var(--err)', fontSize:12 }}>
          <strong>Errore caricamento audit:</strong> {error}
        </div>
      )}

      <div className="card">
        <div className="card-header">
          <div className="title">Stream eventi audit ({total.toLocaleString('it-IT')})</div>
          <div className="actions">
            <select value={pageSize} onChange={e => setPageSize(Number(e.target.value))} style={{fontSize: 11}}>
              {[25, 50, 100, 250].map(s => <option key={s} value={s}>{s} per pagina</option>)}
            </select>
          </div>
        </div>
        <table className="tbl dense">
          <thead><tr>
            <th style={{width: 180}}>Timestamp</th>
            <th style={{width: 160}}>Attore</th>
            <th style={{width: 100}}>Azione</th>
            <th style={{width: 180}}>Entity type</th>
            <th>Entity ID</th>
            <th style={{width: 70, textAlign: 'center'}}>Diff</th>
            <th style={{width: 90, textAlign: 'center'}}>Versione</th>
          </tr></thead>
          <tbody>
            {data.length === 0 && !loading && (
              <tr><td colSpan={7} style={{textAlign: 'center', padding: 20, color: 'var(--text-3)', fontSize: 11.5}}>
                Nessun evento corrispondente ai filtri.
              </td></tr>
            )}
            {data.map(r => {
              const hasDiff = r.diff && (r.diff.before !== undefined || r.diff.after !== undefined);
              return (
                <tr key={r.id} className="clickable" onClick={() => setSel(r)}>
                  <td className="mono" style={{fontSize: 10.5, color: 'var(--text-3)'}}>{new Date(r.ts).toLocaleString('it-IT')}</td>
                  <td style={{fontSize: 11.5}}>
                    {r.actorType === 'system' ? <Chip kind="ai">sistema</Chip> : <span>{personaName(r.actorPersonaId)}</span>}
                  </td>
                  <td><Chip kind={r.action === 'create' ? 'ok' : r.action === 'delete' ? 'err' : r.action === 'publish' ? 'info' : ''} dot>{r.action}</Chip></td>
                  <td className="mono" style={{fontSize: 11}}>{r.entityType}</td>
                  <td className="mono" style={{fontSize: 11, color: 'var(--text-2)'}}>{r.entityId}</td>
                  <td style={{textAlign: 'center'}}>
                    {hasDiff ? <Chip kind="info">diff</Chip> : <span style={{color: 'var(--text-3)'}}>—</span>}
                  </td>
                  <td style={{textAlign: 'center', fontSize: 10, color: 'var(--text-3)'}}>{r.configVersionId ? r.configVersionId.slice(0, 12) + '…' : '—'}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
        {loading && (
          <div style={{padding: 14, textAlign: 'center', color: 'var(--text-3)', fontSize: 11.5}}>Caricamento…</div>
        )}
        {/* Paginazione */}
        <div className="card-body" style={{padding: 10, borderTop: '1px solid var(--line)', display: 'flex', alignItems: 'center', gap: 8}}>
          <span style={{fontSize: 11, color: 'var(--text-3)'}}>
            Pagina {page} di {totalPages} · {data.length} di {total} mostrati
          </span>
          <span className="spacer"/>
          <Btn variant="ghost" size="sm" disabled={page <= 1 || loading} onClick={() => setPage(1)}><Icon name="chev_l" size={11}/><Icon name="chev_l" size={11}/></Btn>
          <Btn variant="ghost" size="sm" disabled={page <= 1 || loading} onClick={() => setPage(p => Math.max(1, p - 1))}><Icon name="chev_l" size={11}/></Btn>
          <Btn variant="ghost" size="sm" disabled={page >= totalPages || loading} onClick={() => setPage(p => Math.min(totalPages, p + 1))}><Icon name="chev_r" size={11}/></Btn>
          <Btn variant="ghost" size="sm" disabled={page >= totalPages || loading} onClick={() => setPage(totalPages)}><Icon name="chev_r" size={11}/><Icon name="chev_r" size={11}/></Btn>
        </div>
      </div>

      {sel && <AuditDetailModal row={sel} onClose={() => setSel(null)} personaName={personaName}/>}
    </div>
  );
}

function AuditDetailModal({ row, onClose, personaName }) {
  const diff = row.diff || {};
  const before = diff.before;
  const after = diff.after;

  // Estrai i campi cambiati (intersezione delle chiavi se entrambi presenti, oppure tutto if uno è null)
  const changedKeys = React.useMemo(() => {
    const keys = new Set();
    if (before && typeof before === 'object') Object.keys(before).forEach(k => keys.add(k));
    if (after && typeof after === 'object') Object.keys(after).forEach(k => keys.add(k));
    return [...keys].sort();
  }, [before, after]);

  return (
    <Modal open onClose={onClose} title={`Audit · ${row.action} ${row.entityType} ${row.entityId}`} size="xl" footer={<>
      <Btn variant="ghost" size="sm" onClick={onClose}>Chiudi</Btn>
    </>}>
      <div className="col" style={{gap: 14}}>
        <div className="grid grid-3" style={{fontSize: 11.5}}>
          <div><span style={{color: 'var(--text-3)'}}>Timestamp</span><br/><span className="mono">{new Date(row.ts).toLocaleString('it-IT')}</span></div>
          <div><span style={{color: 'var(--text-3)'}}>Attore</span><br/>
            {row.actorType === 'system' ? <Chip kind="ai">sistema</Chip> : <span>{personaName(row.actorPersonaId)} <code style={{fontSize: 10}}>{row.actorPersonaId}</code></span>}
          </div>
          <div><span style={{color: 'var(--text-3)'}}>IP / UA</span><br/>
            <span className="mono" style={{fontSize: 10.5}}>{row.ip || '—'}</span>
            {row.userAgent && <span style={{fontSize: 10, color: 'var(--text-3)', display: 'block'}}>{row.userAgent.slice(0, 60)}</span>}
          </div>
          <div><span style={{color: 'var(--text-3)'}}>Entity type</span><br/><Chip>{row.entityType}</Chip></div>
          <div><span style={{color: 'var(--text-3)'}}>Entity ID</span><br/><span className="mono" style={{fontSize: 11}}>{row.entityId}</span></div>
          <div><span style={{color: 'var(--text-3)'}}>Azione</span><br/><Chip kind={row.action === 'create' ? 'ok' : row.action === 'delete' ? 'err' : row.action === 'publish' ? 'info' : ''} dot>{row.action}</Chip></div>
          {row.configVersionId && <div style={{gridColumn: 'span 3'}}><span style={{color: 'var(--text-3)'}}>Config version</span><br/><span className="mono" style={{fontSize: 11}}>{row.configVersionId}</span></div>}
        </div>

        <div>
          <div className="eyebrow" style={{marginBottom: 6}}>Diff before / after ({changedKeys.length} campi)</div>
          {changedKeys.length === 0 ? (
            <div style={{fontSize: 11.5, color: 'var(--text-3)', padding: 12, textAlign: 'center', background: 'var(--bg-2)', borderRadius: 4}}>
              Nessun campo modificato (no-op o action senza diff).
            </div>
          ) : (
            <table className="tbl dense">
              <thead><tr>
                <th style={{width: 140}}>Campo</th>
                <th>Prima</th>
                <th>Dopo</th>
              </tr></thead>
              <tbody>
                {changedKeys.map(k => (
                  <tr key={k}>
                    <td className="mono" style={{fontSize: 11, fontWeight: 500}}>{k}</td>
                    <td style={{fontSize: 11, fontFamily: 'var(--font-mono)', color: 'var(--text-2)', verticalAlign: 'top', maxWidth: 400, wordBreak: 'break-all'}}>
                      {formatDiffValue(before && before[k])}
                    </td>
                    <td style={{fontSize: 11, fontFamily: 'var(--font-mono)', verticalAlign: 'top', maxWidth: 400, wordBreak: 'break-all'}}>
                      {formatDiffValue(after && after[k])}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
        </div>

        <details>
          <summary style={{cursor: 'pointer', fontSize: 12, color: 'var(--text-2)'}}>Hash chain (debug)</summary>
          <div style={{marginTop: 8, fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--text-3)', wordBreak: 'break-all'}}>
            <div>prev: {row.hashPrev || '(genesis)'}</div>
            <div>curr: {row.hashCurr}</div>
          </div>
        </details>
      </div>
    </Modal>
  );
}

function formatDiffValue(v) {
  if (v === null || v === undefined) return <span style={{color: 'var(--text-3)'}}>(null)</span>;
  if (typeof v === 'boolean') return v ? 'true' : 'false';
  if (typeof v === 'string') return v.length > 100 ? v.slice(0, 100) + '…' : v;
  if (typeof v === 'number') return String(v);
  // object/array → JSON pretty truncated
  const json = JSON.stringify(v, null, 2);
  return json.length > 200 ? json.slice(0, 200) + '…' : json;
}

Object.assign(window, { Audit });
