const { useState, useEffect, useCallback, useMemo } = React;

const STATES = ['bozza_ai','supervisione_fornitore','revisione_cliente','validazione_rup','firmato'];
const STATE_LABELS = {
  bozza_ai: 'Bozza AI',
  supervisione_fornitore: 'Supervisione Fornitore',
  revisione_cliente: 'Revisione Cliente',
  validazione_rup: 'Validazione RUP',
  firmato: 'Firmato / Definitivo'
};
const ROLE_LABELS = {
  amministrativo_pa: 'Amministrativo PA',
  fornitore: 'Fornitore',
  cliente_amministrativo: 'Cliente Amministrativo',
  rup: 'RUP',
  admin: 'Amministratore'
};
const DOC_TYPES = [
  { value: 'bando',        label: 'Bando di gara' },
  { value: 'disciplinare', label: 'Disciplinare di gara' },
  { value: 'capitolato',   label: 'Capitolato' },
  { value: 'invito',       label: 'Lettera d’invito' },
  { value: 'determina',    label: 'Determina a contrarre' }
];

const api = {
  token: () => localStorage.getItem('dockratos_token'),
  setToken: (t) => t ? localStorage.setItem('dockratos_token', t) : localStorage.removeItem('dockratos_token'),
  user: () => JSON.parse(localStorage.getItem('dockratos_user') || 'null'),
  setUser: (u) => u ? localStorage.setItem('dockratos_user', JSON.stringify(u)) : localStorage.removeItem('dockratos_user'),
  async call(path, opts = {}) {
    const res = await fetch(path, {
      ...opts,
      headers: {
        'Content-Type': 'application/json',
        ...(api.token() ? { Authorization: `Bearer ${api.token()}` } : {}),
        ...(opts.headers || {})
      }
    });
    if (!res.ok) {
      let msg = res.statusText;
      try { msg = (await res.json()).error || msg; } catch {}
      throw new Error(msg);
    }
    return res.status === 204 ? null : res.json();
  }
};

function Login({ onLogin }) {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(false);

  async function submit(e) {
    e.preventDefault();
    setError(''); setLoading(true);
    try {
      const { token, user } = await api.call('/api/auth/login', { method: 'POST', body: JSON.stringify({ email, password }) });
      api.setToken(token); api.setUser(user);
      onLogin(user);
    } catch (e) { setError(e.message); }
    finally { setLoading(false); }
  }

  return (
    <main id="main" className="login-card card">
      <img src="/assets/logo.jpg" alt="Logo DocKratos" className="logo" />
      <h2 style={{textAlign:'center', marginTop:0}}>Accedi a DocKratos</h2>
      {error && <div className="error" role="alert">{error}</div>}
      <form onSubmit={submit} aria-label="Modulo di accesso">
        <label htmlFor="email">Email</label>
        <input id="email" type="email" required value={email} onChange={e => setEmail(e.target.value)} autoComplete="username" />
        <label htmlFor="password">Password</label>
        <input id="password" type="password" required value={password} onChange={e => setPassword(e.target.value)} autoComplete="current-password" />
        <button type="submit" className="primary" style={{marginTop:'1.5rem', width:'100%'}} disabled={loading}>
          {loading ? 'Accesso in corso…' : 'Accedi'}
        </button>
      </form>
    </main>
  );
}

function Stepper({ current }) {
  const idx = STATES.indexOf(current);
  return (
    <ol className="stepper" aria-label="Fasi del workflow">
      {STATES.map((s, i) => {
        const cls = i < idx ? 'step done' : i === idx ? 'step current' : 'step';
        return <li key={s} className={cls} aria-current={i === idx ? 'step' : undefined}>{i+1}. {STATE_LABELS[s]}</li>;
      })}
    </ol>
  );
}

function DocumentList({ user, onOpen, onNew }) {
  const [docs, setDocs] = useState([]);
  const [error, setError] = useState('');
  const [filter, setFilter] = useState('');

  const load = useCallback(async () => {
    try {
      const { documents } = await api.call('/api/documents');
      setDocs(documents);
    } catch (e) { setError(e.message); }
  }, []);

  useEffect(() => { load(); }, [load]);

  const filtered = docs.filter(d => !filter || d.title.toLowerCase().includes(filter.toLowerCase()));

  return (
    <div className="card">
      <div style={{display:'flex', gap:'1rem', alignItems:'center', marginBottom:'1rem', flexWrap:'wrap'}}>
        <h2 style={{margin:0}}>Documenti</h2>
        <input type="search" placeholder="Cerca per titolo…" value={filter} onChange={e => setFilter(e.target.value)} style={{flex:'1 1 200px', maxWidth:400}} aria-label="Cerca documenti" />
        {user.role === 'amministrativo_pa' && (
          <button className="primary" onClick={onNew}>+ Nuovo documento</button>
        )}
      </div>
      {error && <div className="error" role="alert">{error}</div>}
      <table>
        <caption style={{position:'absolute', left:-9999}}>Elenco documenti</caption>
        <thead>
          <tr>
            <th scope="col">Tipo</th>
            <th scope="col">Titolo</th>
            <th scope="col">Stato</th>
            <th scope="col">Protocollo</th>
            <th scope="col">Aggiornato</th>
            <th scope="col">Azione</th>
          </tr>
        </thead>
        <tbody>
          {filtered.map(d => (
            <tr key={d.id}>
              <td>{DOC_TYPES.find(t => t.value === d.type)?.label || d.type}</td>
              <td>{d.title}</td>
              <td><span className={`badge state-${d.state}`}>{STATE_LABELS[d.state]}</span></td>
              <td>{d.protocol_number ? `${d.protocol_number}/${(d.protocol_date || '').slice(0,4)}` : '—'}</td>
              <td>{d.updated_at}</td>
              <td><button onClick={() => onOpen(d.id)}>Apri</button></td>
            </tr>
          ))}
          {filtered.length === 0 && (
            <tr><td colSpan="6" style={{textAlign:'center', padding:'2rem', color:'#6b6b6b'}}>Nessun documento visibile per il tuo ruolo.</td></tr>
          )}
        </tbody>
      </table>
    </div>
  );
}

function NewDocument({ onCreated, onCancel }) {
  const [type, setType] = useState('bando');
  const [title, setTitle] = useState('');
  const [oggetto, setOggetto] = useState('');
  const [cig, setCig] = useState('');
  const [error, setError] = useState('');

  async function submit(e) {
    e.preventDefault();
    try {
      const { id } = await api.call('/api/documents', { method: 'POST', body: JSON.stringify({ type, title, oggetto, cig, content: '' }) });
      onCreated(id);
    } catch (e) { setError(e.message); }
  }
  return (
    <div className="card">
      <h2>Nuovo documento</h2>
      {error && <div className="error" role="alert">{error}</div>}
      <form onSubmit={submit}>
        <label htmlFor="type">Tipo</label>
        <select id="type" value={type} onChange={e => setType(e.target.value)}>
          {DOC_TYPES.map(t => <option key={t.value} value={t.value}>{t.label}</option>)}
        </select>
        <label htmlFor="title">Titolo</label>
        <input id="title" required value={title} onChange={e => setTitle(e.target.value)} />
        <label htmlFor="oggetto">Oggetto (per protocollo)</label>
        <input id="oggetto" value={oggetto} onChange={e => setOggetto(e.target.value)} />
        <label htmlFor="cig">CIG (opzionale)</label>
        <input id="cig" value={cig} onChange={e => setCig(e.target.value)} />
        <div style={{marginTop:'1.5rem', display:'flex', gap:'0.5rem'}}>
          <button type="submit" className="primary">Crea</button>
          <button type="button" className="ghost" onClick={onCancel}>Annulla</button>
        </div>
      </form>
    </div>
  );
}

function DocumentEditor({ user, docId, onBack }) {
  const [doc, setDoc] = useState(null);
  const [versions, setVersions] = useState([]);
  const [transitions, setTransitions] = useState([]);
  const [signatures, setSignatures] = useState([]);
  const [content, setContent] = useState('');
  const [notes, setNotes] = useState('');
  const [aiPrompt, setAiPrompt] = useState('');
  const [aiBusy, setAiBusy] = useState(false);
  const [msg, setMsg] = useState('');
  const [error, setError] = useState('');

  const canEdit = useMemo(() => {
    if (!doc || !user) return false;
    if (doc.state === 'firmato') return false;
    const roleForState = {
      bozza_ai: 'amministrativo_pa',
      supervisione_fornitore: 'fornitore',
      revisione_cliente: 'cliente_amministrativo',
      validazione_rup: 'rup'
    };
    return user.role === 'admin' || user.role === roleForState[doc.state];
  }, [doc, user]);

  const load = useCallback(async () => {
    setError('');
    try {
      const data = await api.call(`/api/documents/${docId}`);
      setDoc(data.document);
      setContent(data.document.content || '');
      setVersions(data.versions);
      setTransitions(data.transitions);
      setSignatures(data.signatures);
    } catch (e) { setError(e.message); }
  }, [docId]);

  useEffect(() => { load(); }, [load]);

  if (!doc) return <div className="card">Caricamento…</div>;

  async function save() {
    setMsg(''); setError('');
    try { await api.call(`/api/documents/${doc.id}`, { method: 'PATCH', body: JSON.stringify({ content }) }); setMsg('Salvato.'); load(); }
    catch (e) { setError(e.message); }
  }
  async function advance() {
    setMsg(''); setError('');
    try {
      const r = await api.call(`/api/documents/${doc.id}/advance`, { method: 'POST', body: JSON.stringify({ notes }) });
      setMsg(`Avanzato a "${STATE_LABELS[r.state]}"`); setNotes(''); load();
    } catch (e) { setError(e.message); }
  }
  async function regress() {
    setMsg(''); setError('');
    try {
      const r = await api.call(`/api/documents/${doc.id}/regress`, { method: 'POST', body: JSON.stringify({ notes }) });
      setMsg(`Rimandato a "${STATE_LABELS[r.state]}"`); setNotes(''); load();
    } catch (e) { setError(e.message); }
  }
  async function protocol() {
    setMsg(''); setError('');
    try {
      const r = await api.call(`/api/documents/${doc.id}/protocol`, { method: 'POST', body: JSON.stringify({}) });
      const blob = new Blob([r.segnatura_xml], { type: 'application/xml' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a'); a.href = url; a.download = `segnatura_${r.protocol_number}.xml`; a.click(); URL.revokeObjectURL(url);
      setMsg(`Protocollato n. ${r.protocol_number}/${r.protocol_date.slice(0,4)}. Segnatura XML scaricata.`);
      load();
    } catch (e) { setError(e.message); }
  }
  async function sign() {
    setMsg(''); setError('');
    if (!confirm('Confermi la firma digitale (formato PAdES)?\nATTENZIONE: nel MVP la firma è simulata (stub).')) return;
    try {
      const r = await api.call(`/api/documents/${doc.id}/sign`, { method: 'POST', body: JSON.stringify({ format: 'PAdES' }) });
      setMsg(`Firmato. ${r.warning || ''}`); load();
    } catch (e) { setError(e.message); }
  }
  async function aiGenerate() {
    setAiBusy(true); setMsg(''); setError('');
    try {
      const r = await api.call('/api/ai/generate', { method: 'POST', body: JSON.stringify({ type: doc.type, prompt: aiPrompt, context: { titolo: doc.title, oggetto: doc.oggetto, cig: doc.cig } }) });
      setContent((content ? content + '\n\n---\n\n' : '') + r.text);
      setMsg(`Bozza generata (modello: ${r.model})`);
    } catch (e) { setError(`AI non disponibile: ${e.message}. Verifica che Ollama sia in esecuzione su http://localhost:11434`); }
    finally { setAiBusy(false); }
  }

  return (
    <div>
      <button className="ghost" onClick={onBack} aria-label="Torna all'elenco">&larr; Elenco</button>
      <div className="card" style={{marginTop:'0.75rem'}}>
        <h2 style={{marginTop:0}}>{doc.title} <span className={`badge state-${doc.state}`}>{STATE_LABELS[doc.state]}</span></h2>
        <p style={{color:'#6b6b6b', marginTop:0}}>
          Tipo: <strong>{DOC_TYPES.find(t => t.value === doc.type)?.label}</strong> ·
          Creato da: {doc.created_by_name} ·
          {doc.protocol_number && <> Protocollo: <strong>{doc.protocol_number}/{(doc.protocol_date || '').slice(0,4)}</strong> · </>}
          {doc.cig && <> CIG: {doc.cig}</>}
        </p>
        <Stepper current={doc.state} />
        {msg && <div className="notice" role="status">{msg}</div>}
        {error && <div className="error" role="alert">{error}</div>}
      </div>

      {canEdit && doc.state === 'bozza_ai' && (
        <div className="card">
          <h3 style={{marginTop:0}}>Assistente AI locale</h3>
          <p style={{color:'#6b6b6b'}}>Genera una bozza con Ollama in esecuzione locale (nessun dato inviato a fornitori esterni).</p>
          <label htmlFor="ai">Descrizione strutturata</label>
          <textarea id="ai" rows="4" placeholder="Es. Bando per fornitura di 100 licenze software gestionale, importo a base d'asta 60.000 euro, procedura affidamento diretto ex art. 50…"
            value={aiPrompt} onChange={e => setAiPrompt(e.target.value)} />
          <button className="primary" onClick={aiGenerate} disabled={aiBusy || !aiPrompt} style={{marginTop:'0.75rem'}}>
            {aiBusy ? 'Generazione…' : 'Genera bozza'}
          </button>
        </div>
      )}

      <div className="card">
        <h3 style={{marginTop:0}}>Contenuto</h3>
        <label htmlFor="content" className="sr-only">Testo del documento</label>
        <textarea id="content" value={content} onChange={e => setContent(e.target.value)} readOnly={!canEdit} aria-readonly={!canEdit} />
        {canEdit && (
          <div style={{marginTop:'0.75rem', display:'flex', gap:'0.5rem'}}>
            <button className="primary" onClick={save}>Salva</button>
          </div>
        )}
      </div>

      <div className="card">
        <h3 style={{marginTop:0}}>Azioni di workflow</h3>
        <label htmlFor="notes">Note (opzionali, tracciate in audit)</label>
        <textarea id="notes" rows="2" value={notes} onChange={e => setNotes(e.target.value)} />
        <div style={{display:'flex', gap:'0.5rem', flexWrap:'wrap', marginTop:'0.75rem'}}>
          {doc.state !== 'firmato' && doc.state !== 'validazione_rup' && (
            <button className="primary" onClick={advance}>Avanza →</button>
          )}
          {doc.state === 'validazione_rup' && user.role === 'rup' && (
            <button className="primary" onClick={sign}>✍ Firma digitale (PAdES)</button>
          )}
          {doc.state !== 'bozza_ai' && doc.state !== 'firmato' && (
            <button className="ghost" onClick={regress}>← Rimanda indietro</button>
          )}
          {(user.role === 'amministrativo_pa' || user.role === 'rup') && !doc.protocol_number && (
            <button onClick={protocol}>Protocolla (segnatura.xml)</button>
          )}
        </div>
      </div>

      <div className="row">
        <div className="card">
          <h3 style={{marginTop:0}}>Storia versioni</h3>
          {versions.length === 0 ? <p>Nessuna versione ancora.</p> : (
            <ul>
              {versions.map(v => <li key={v.id}>v.{v.version_num} — {v.snapshot_at} — {v.snapshot_by_name} — hash <code style={{fontSize:'0.75rem'}}>{v.content_hash.slice(0,16)}…</code></li>)}
            </ul>
          )}
        </div>
        <div className="card">
          <h3 style={{marginTop:0}}>Transizioni workflow</h3>
          {transitions.length === 0 ? <p>Nessuna transizione.</p> : (
            <ul>
              {transitions.map(t => <li key={t.id}>{t.timestamp}: {t.from_state || '—'} → <strong>{STATE_LABELS[t.to_state]}</strong> ({t.actor_name}){t.notes ? ` — ${t.notes}` : ''}</li>)}
            </ul>
          )}
        </div>
        <div className="card">
          <h3 style={{marginTop:0}}>Firme</h3>
          {signatures.length === 0 ? <p>Nessuna firma.</p> : (
            <ul>{signatures.map(s => <li key={s.id}>{s.timestamp}: {s.signature_type} da {s.signer_name} — provider: {s.provider}</li>)}</ul>
          )}
        </div>
      </div>
    </div>
  );
}

function App() {
  const [user, setUser] = useState(api.user());
  const [view, setView] = useState('list'); // list | new | edit
  const [openId, setOpenId] = useState(null);

  useEffect(() => {
    if (user) {
      api.call('/api/auth/me').then(r => setUser(r.user)).catch(() => {
        api.setToken(null); api.setUser(null); setUser(null);
      });
    }
  }, []);

  function logout() { api.setToken(null); api.setUser(null); setUser(null); setView('list'); }

  if (!user) return <Login onLogin={setUser} />;

  return (
    <>
      <header className="topbar">
        <img src="/assets/logo.jpg" alt="DocKratos" className="logo" />
        <h1>DocKratos</h1>
        <div className="who">
          {user.name} · <strong>{ROLE_LABELS[user.role]}</strong>
          &nbsp;·&nbsp; <button className="ghost" onClick={logout} style={{padding:'0.25rem 0.5rem', minHeight:'auto'}}>Esci</button>
        </div>
      </header>
      <nav className="tabs" aria-label="Sezioni">
        <button aria-current={view === 'list' ? 'page' : undefined} onClick={() => { setView('list'); setOpenId(null); }}>Documenti</button>
      </nav>
      <main id="main">
        {view === 'list' && <DocumentList user={user} onOpen={(id) => { setOpenId(id); setView('edit'); }} onNew={() => setView('new')} />}
        {view === 'new' && <NewDocument onCreated={(id) => { setOpenId(id); setView('edit'); }} onCancel={() => setView('list')} />}
        {view === 'edit' && openId && <DocumentEditor user={user} docId={openId} onBack={() => { setOpenId(null); setView('list'); }} />}
      </main>
      <footer className="footer">
        DocKratos · piattaforma self-hosted · licenza AGPL-3.0-or-later ·
        <a href="/docs/DocKratos_brief_normativo_PA.md" style={{marginLeft:'0.5rem'}}>Brief normativo</a>
      </footer>
    </>
  );
}

const root = ReactDOM.createRoot(document.getElementById('app'));
root.render(<App />);
