// --- Promemoria "Da fatturare" — note interne, convertibili in fattura ----

const P_STATUSES = ['aperto', 'parzialmente_fatturato', 'fatturato', 'archiviato', 'annullato'];

function pendingBadge(status) {
  const st = window.STATUSES[status] || window.STATUSES.aperto;
  return <span className={`badge ${st.cls}`}><span className="badge-dot" style={{ background: st.dot }} />{st.label}</span>;
}

async function apiP(url, opts = {}) {
  const r = await fetch(url, {
    credentials: 'include',
    headers: { 'Content-Type': 'application/json', ...(opts.headers || {}) },
    ...opts,
    body: opts.body && typeof opts.body !== 'string' ? JSON.stringify(opts.body) : opts.body,
  });
  const ct = r.headers.get('content-type') || '';
  const data = ct.includes('json') ? await r.json().catch(() => null) : await r.text();
  if (!r.ok) throw new Error((data && data.error) || `HTTP ${r.status}`);
  return data;
}

// ============================================================================
// LISTA + KPI
// ============================================================================
function PendingScreen({ param, onNav }) {
  // Wrapper: monta dettaglio o lista (no hooks qui per evitare hook-order issues)
  if (param && /^\d+$/.test(param)) {
    return <PendingDetail key={'pd-' + param} id={Number(param)} onBack={() => onNav('pending')} onNav={onNav} />;
  }
  return <PendingList onNav={onNav} />;
}

function PendingList({ onNav }) {
  const [docs, setDocs] = useState([]);
  const [stats, setStats] = useState(null);
  const [filter, setFilter] = useState('aperti');
  const [q, setQ] = useState('');
  const [clientFilter, setClientFilter] = useState('all');
  const [clients, setClients] = useState([]);
  const [loading, setLoading] = useState(true);
  const [showNew, setShowNew] = useState(false);
  const [showConvert, setShowConvert] = useState(false);

  const load = () => {
    setLoading(true);
    Promise.all([
      window.LibroAPI.pendingList(),
      window.LibroAPI.pendingStats().catch(() => null),
      window.LibroAPI.clients(),
    ]).then(([list, st, cs]) => {
      setDocs(list || []); setStats(st); setClients(cs || []);
      setLoading(false);
    }).catch(() => setLoading(false));
  };
  useEffect(load, []);

  const rows = useMemo(() => docs.filter((d) => {
    if (filter === 'aperti'      && !['aperto', 'parzialmente_fatturato'].includes(d.status)) return false;
    if (filter === 'fatturati'   && d.status !== 'fatturato') return false;
    if (filter === 'archiviati'  && d.status !== 'archiviato') return false;
    if (filter === 'annullati'   && d.status !== 'annullato') return false;
    if (clientFilter !== 'all' && String(d.client_id) !== String(clientFilter)) return false;
    if (q) {
      const ql = q.toLowerCase();
      const hay = `${d.title || ''} ${d.notes || ''} ${d.client?.name || ''}`.toLowerCase();
      if (!hay.includes(ql)) return false;
    }
    return true;
  }), [docs, filter, clientFilter, q]);

  const counts = {
    tutti: docs.length,
    aperti: docs.filter((d) => ['aperto', 'parzialmente_fatturato'].includes(d.status)).length,
    fatturati: docs.filter((d) => d.status === 'fatturato').length,
    archiviati: docs.filter((d) => d.status === 'archiviato').length,
    annullati: docs.filter((d) => d.status === 'annullato').length,
  };

  const totaleAperto = stats?.totale_aperto || 0;

  return (
    <>
      <Topbar crumbs={['Gestionale', 'Amministrazione', 'Da fatturare']} />
      <div className="content">
        <div className="page-head">
          <div>
            <h1 className="page-title">Da fatturare <em>{counts.aperti}</em></h1>
            <div className="page-sub">Note interne · righe accumulate nel tempo · convertibili in fattura</div>
          </div>
          <div style={{ display: 'flex', gap: 8 }}>
            <button className="btn btn-ghost btn-lg" onClick={() => setShowConvert(true)} title="Crea fattura selezionando righe da promemoria">
              <Icon name="receipt" size={15} /> Crea fattura
            </button>
            <button className="btn btn-accent btn-lg" onClick={() => setShowNew(true)}>
              <Icon name="plus" size={15} /> Nuovo promemoria
            </button>
          </div>
        </div>

        <div className="kpi-strip">
          {[
            { label: 'Aperti',      value: counts.aperti,    ic: 'inbox', nonEuro: true },
            { label: 'Totale dovuto', value: totaleAperto,   ic: 'wallet' },
            { label: 'Fatturati',   value: counts.fatturati, ic: 'check-circle-2', nonEuro: true },
            { label: 'Totali',      value: counts.tutti,     ic: 'clipboard-list', nonEuro: true },
          ].map((k, i) => {
            const { intp, cent } = fmtEURSplit(k.value || 0);
            return (
              <div key={i} className="kpi">
                <div className="kpi-label"><Icon name={k.ic} size={12} stroke={2} />{k.label}</div>
                <div className="kpi-value">
                  {!k.nonEuro && <span style={{ color: 'var(--ink-3)', fontSize: 18, marginRight: 2, fontWeight: 400 }}>€</span>}
                  {k.nonEuro ? k.value : <>{intp}<span className="cent">,{cent}</span></>}
                </div>
              </div>
            );
          })}
        </div>

        <div className="tabs">
          {[
            { id: 'aperti', l: 'Aperti', c: counts.aperti },
            { id: 'fatturati', l: 'Fatturati', c: counts.fatturati },
            { id: 'archiviati', l: 'Archiviati', c: counts.archiviati },
            { id: 'annullati', l: 'Annullati', c: counts.annullati },
            { id: 'tutti', l: 'Tutti', c: counts.tutti },
          ].map((t) => (
            <div key={t.id} className={`tab ${filter === t.id ? 'active' : ''}`} onClick={() => setFilter(t.id)}>
              {t.l}<span className="c">{t.c}</span>
            </div>
          ))}
        </div>

        <div className="filter-row">
          <select className="select-sm" value={clientFilter} onChange={(e) => setClientFilter(e.target.value)}>
            <option value="all">Tutti i clienti</option>
            {clients.map((c) => <option key={c.id} value={c.id}>{c.name}</option>)}
          </select>
          <div className="search-wrap">
            <Icon name="search" size={14} />
            <input className="input" placeholder="Cerca per titolo, note, cliente…" value={q} onChange={(e) => setQ(e.target.value)} />
          </div>
        </div>

        <div className="table-wrap">
          <table className="invoices">
            <thead>
              <tr>
                <th>Cliente</th>
                <th>Titolo</th>
                <th style={{ width: 70, textAlign: 'right' }}>Righe</th>
                <th style={{ width: 140, textAlign: 'right' }}>Aperto</th>
                <th style={{ width: 140, textAlign: 'right' }}>Fatturato</th>
                <th style={{ width: 140 }}>Stato</th>
                <th style={{ width: 110 }}>Aggiornato</th>
              </tr>
            </thead>
            <tbody>
              {loading && <tr><td colSpan={7} style={{ textAlign: 'center', padding: 40, color: 'var(--ink-3)' }}>Caricamento…</td></tr>}
              {!loading && rows.length === 0 && (
                <tr><td colSpan={7} style={{ textAlign: 'center', padding: 40, color: 'var(--ink-3)' }}>
                  <Icon name="inbox" size={20} style={{ margin: '0 auto 8px' }} />
                  <div>Nessun promemoria con questi filtri</div>
                  <div style={{ marginTop: 10 }}>
                    <button className="btn btn-accent" onClick={() => setShowNew(true)}><Icon name="plus" size={13} /> Crea il primo</button>
                  </div>
                </td></tr>
              )}
              {!loading && rows.map((d) => (
                <tr key={d.id} onClick={() => onNav('pending/' + d.id)} style={{ cursor: 'pointer' }}>
                  <td data-label="Cliente">
                    <div className="client-cell">
                      <div className="client-mark">{d.client?.short || '??'}</div>
                      <div>
                        <div className="client-name">{d.client?.name || '—'}</div>
                        {d.client?.type && <div className="client-sub">{d.client.type}</div>}
                      </div>
                    </div>
                  </td>
                  <td data-label="Titolo">
                    <div style={{ fontWeight: 500 }}>{d.title || <span style={{ color: 'var(--ink-3)' }}>(senza titolo)</span>}</div>
                    {d.notes && <div style={{ fontSize: 11.5, color: 'var(--ink-3)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: 320 }}>{d.notes}</div>}
                  </td>
                  <td data-label="Righe" className={'amount mono ' + ((d.lines_count || 0) === 0 ? 'cell-empty' : '')}>{d.lines_count}</td>
                  <td data-label="Aperto" className={'amount total mono ' + ((d.totale_aperto || 0) === 0 ? 'cell-empty' : '')}><span className="euro">€</span>{new Intl.NumberFormat('it-IT', { minimumFractionDigits: 2 }).format(d.totale_aperto || 0)}</td>
                  <td data-label="Fatturato" className={'amount mono ' + ((d.totale_fatturato || 0) === 0 ? 'cell-empty' : '')} style={{ color: 'var(--ink-3)' }}><span className="euro">€</span>{new Intl.NumberFormat('it-IT', { minimumFractionDigits: 2 }).format(d.totale_fatturato || 0)}</td>
                  <td data-label="Stato">{pendingBadge(d.status)}</td>
                  <td data-label="Aggiornato" className="mono" style={{ fontSize: 12.5, color: 'var(--ink-2)' }}>{fmtDate(d.updated_at)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      {showNew && <PendingNewForm clients={clients} onClose={() => setShowNew(false)} onCreated={(id) => { setShowNew(false); load(); onNav('pending/' + id); }} />}
      {showConvert && <PendingConvertModal clients={clients} onClose={() => setShowConvert(false)} onCreated={(invoiceId) => { setShowConvert(false); load(); onNav('invoices/' + invoiceId); }} />}
    </>
  );
}

// ============================================================================
// FORM NUOVO PROMEMORIA
// ============================================================================
function PendingNewForm({ clients, presetClientId, onClose, onCreated }) {
  const [clientId, setClientId] = useState(presetClientId || '');
  const [title, setTitle] = useState('');
  const [notes, setNotes] = useState('');
  const [search, setSearch] = useState('');
  const [saving, setSaving] = useState(false);
  const [err, setErr] = useState('');

  const filtered = useMemo(() => {
    if (!search) return clients.slice(0, 8);
    const ql = search.toLowerCase();
    return clients.filter((c) => (c.name || '').toLowerCase().includes(ql)).slice(0, 8);
  }, [clients, search]);

  const submit = async (e) => {
    e.preventDefault();
    if (!clientId) { setErr('Seleziona un cliente'); return; }
    setSaving(true); setErr('');
    try {
      const created = await window.LibroAPI.createPending({ client_id: Number(clientId), title: title || null, notes: notes || null });
      onCreated(created.id);
    } catch (ex) { setErr(ex.message); }
    finally { setSaving(false); }
  };

  const selectedClient = clients.find((c) => String(c.id) === String(clientId));

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <form className="modal" onClick={(e) => e.stopPropagation()} onSubmit={submit} style={{ width: 480 }}>
        <div className="modal-head">
          <div>
            <div style={{ fontSize: 11, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.1em' }}>Nuovo promemoria</div>
            <h2 style={{ fontFamily: 'Fraunces', fontSize: 20, fontWeight: 500, margin: '4px 0 0' }}>Da fatturare</h2>
          </div>
          <button type="button" className="btn btn-ic btn-ghost" onClick={onClose}><Icon name="x" size={14} /></button>
        </div>
        <div className="modal-body">
          {err && <div className="err" style={{ marginBottom: 12 }}><Icon name="alert-circle" size={14} /> {err}</div>}

          <div className="field"><label className="label">Cliente *</label>
            {selectedClient ? (
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 10px', background: 'var(--paper-3)', borderRadius: 6 }}>
                <div className="client-mark">{selectedClient.short}</div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontWeight: 500 }}>{selectedClient.name}</div>
                  <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>{selectedClient.type}</div>
                </div>
                <button type="button" className="btn btn-ghost btn-sm" onClick={() => setClientId('')}>Cambia</button>
              </div>
            ) : (
              <>
                <input className="input" placeholder="Cerca cliente…" value={search} onChange={(e) => setSearch(e.target.value)} autoFocus />
                {filtered.length > 0 && (
                  <div style={{ marginTop: 6, border: '1px solid var(--rule)', borderRadius: 6, maxHeight: 200, overflowY: 'auto' }}>
                    {filtered.map((c) => (
                      <div key={c.id} onClick={() => setClientId(c.id)}
                        style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 10px', cursor: 'pointer', borderBottom: '1px solid var(--rule-2)' }}>
                        <div className="client-mark">{c.short}</div>
                        <div style={{ flex: 1, minWidth: 0 }}>
                          <div style={{ fontSize: 13 }}>{c.name}</div>
                          <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>{c.type}</div>
                        </div>
                      </div>
                    ))}
                  </div>
                )}
              </>
            )}
          </div>

          <div className="field"><label className="label">Titolo (opzionale)</label>
            <input className="input" placeholder="es. Lavori marzo, Consulenze Q2…" value={title} onChange={(e) => setTitle(e.target.value)} />
          </div>

          <div className="field"><label className="label">Note (opzionali)</label>
            <textarea className="textarea" rows={3} value={notes} onChange={(e) => setNotes(e.target.value)} />
          </div>
        </div>
        <div className="modal-foot">
          <button type="button" className="btn btn-ghost" onClick={onClose}>Annulla</button>
          <div style={{ flex: 1 }} />
          <button className="btn btn-accent" type="submit" disabled={saving || !clientId}>{saving ? 'Creazione…' : 'Crea promemoria'}</button>
        </div>
      </form>
    </div>
  );
}

// ============================================================================
// DETTAGLIO PROMEMORIA
// ============================================================================
function PendingDetail({ id, onBack, onNav }) {
  const [doc, setDoc] = useState(null);
  const [err, setErr] = useState('');
  const [editingLine, setEditingLine] = useState(null);
  const [showNewLine, setShowNewLine] = useState(null); // 'manual' | 'task' | 'time_entry'
  const [showConvert, setShowConvert] = useState(false);
  const [saving, setSaving] = useState(false);
  const fileInputRef = useRef(null);

  const load = () => window.LibroAPI.pending(id).then(setDoc).catch((e) => setErr(e.message));
  useEffect(() => { load(); }, [id]);

  const saveHeader = async (patch) => {
    try { const updated = await window.LibroAPI.updatePending(id, patch); setDoc(updated); }
    catch (e) { alert(e.message); }
  };

  const archive = async () => {
    if (!confirm('Archiviare questo promemoria?')) return;
    try { await window.LibroAPI.archivePending(id); load(); } catch (e) { alert(e.message); }
  };
  const unarchive = async () => {
    try { await window.LibroAPI.unarchivePending(id); load(); } catch (e) { alert(e.message); }
  };
  const cancel = async () => {
    if (!confirm('Annullare questo promemoria? Non sarà più conteggiato nel dovuto.')) return;
    try { await window.LibroAPI.cancelPending(id); load(); } catch (e) { alert(e.message); }
  };
  const destroy = async () => {
    const fatturate = (doc?.lines || []).filter((l) => l.line_status === 'fatturato' || l.line_status === 'parzialmente_fatturato').length;
    const msg = fatturate > 0
      ? `Eliminare questo promemoria?\n\n⚠ ${fatturate} riga${fatturate > 1 ? 'he' : ''} risulta${fatturate > 1 ? 'no' : ''} già fatturate. Le fatture collegate restano intatte (le righe pending verranno solo scollegate).`
      : 'Eliminare questo promemoria?';
    if (!confirm(msg)) return;
    try { await window.LibroAPI.deletePending(id); onBack(); } catch (e) { alert(e.message); }
  };

  const deleteLine = async (lineId, line) => {
    const fat = (line.line_status === 'fatturato' || line.line_status === 'parzialmente_fatturato');
    const msg = fat ? '⚠ Questa riga è già fatturata. Eliminandola si scollega dalla fattura (la fattura resta). Continuare?' : 'Eliminare questa riga?';
    if (!confirm(msg)) return;
    try { const updated = await window.LibroAPI.deletePendingLine(id, lineId); setDoc(updated); }
    catch (e) { alert(e.message); }
  };

  const onUploadFile = async (file) => {
    if (!file) return;
    setSaving(true);
    try { await window.LibroAPI.uploadPendingAttachment(id, file); await load(); }
    catch (e) { alert(e.message); }
    finally { setSaving(false); if (fileInputRef.current) fileInputRef.current.value = ''; }
  };
  const deleteAttachment = async (attId) => {
    if (!confirm('Eliminare allegato?')) return;
    try { await window.LibroAPI.deletePendingAttachment(attId); load(); } catch (e) { alert(e.message); }
  };

  if (err) return <div className="content"><div className="err">{err}</div><button className="btn btn-ghost" onClick={onBack}>← Indietro</button></div>;
  if (!doc) return <div className="content" style={{ color: 'var(--ink-3)' }}>Caricamento…</div>;

  const isLocked = doc.status === 'archiviato' || doc.status === 'annullato';
  const lines = doc.lines || [];
  const fatturatePresenti = lines.some((l) => l.line_status === 'fatturato' || l.line_status === 'parzialmente_fatturato');

  return (
    <>
      <Topbar crumbs={['Gestionale', 'Da fatturare', doc.title || `#${doc.id}`]} />
      <div className="content">
        <div className="page-head">
          <div style={{ display: 'flex', alignItems: 'center', gap: 14, minWidth: 0 }}>
            <button className="btn btn-ghost btn-ic" onClick={onBack}><Icon name="arrow-left" size={14} /></button>
            <div style={{ minWidth: 0 }}>
              <h1 className="page-title" style={{ fontSize: 26 }}>
                {doc.title || <em style={{ color: 'var(--ink-3)' }}>Promemoria #{doc.id}</em>}
                <span style={{ marginLeft: 12 }}>{pendingBadge(doc.status)}</span>
              </h1>
              <div className="page-sub">
                <span style={{ cursor: 'pointer', color: 'var(--accent-ink)' }} onClick={() => onNav('clients/' + doc.client_id)}>
                  <Icon name="user" size={11} /> {doc.client?.name}
                </span>
                {' · '}{lines.length} righe · creato {fmtDate(doc.created_at)}
              </div>
            </div>
          </div>
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
            {!isLocked && doc.status !== 'fatturato' && (
              <button className="btn btn-accent" onClick={() => setShowConvert(true)} disabled={lines.length === 0}>
                <Icon name="receipt" size={13} /> Crea fattura
              </button>
            )}
            {doc.status === 'archiviato'
              ? <button className="btn btn-ghost" onClick={unarchive}><Icon name="archive-restore" size={13} /> Ripristina</button>
              : <button className="btn btn-ghost" onClick={archive} disabled={isLocked}><Icon name="archive" size={13} /> Archivia</button>}
            {doc.status !== 'annullato' && <button className="btn btn-ghost" onClick={cancel}><Icon name="ban" size={13} /> Annulla</button>}
            <button className="btn btn-ghost" onClick={destroy}><Icon name="trash-2" size={13} /> Elimina</button>
          </div>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 320px', gap: 16, alignItems: 'start' }}>
          {/* MAIN: Header editable + righe */}
          <div>
            {/* Header editor */}
            <div className="card" style={{ background: '#fff', padding: 16, borderRadius: 10, border: '1px solid var(--rule)', marginBottom: 16 }}>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
                <div className="field"><label className="label">Titolo</label>
                  <input className="input" value={doc.title || ''} onChange={(e) => setDoc({ ...doc, title: e.target.value })} onBlur={() => saveHeader({ title: doc.title })} placeholder="es. Lavori marzo…" disabled={isLocked} />
                </div>
                <div className="field"><label className="label">Cliente</label>
                  <input className="input" value={doc.client?.name || ''} disabled style={{ background: 'var(--paper-3)' }} />
                </div>
              </div>
              <div className="field" style={{ marginBottom: 0 }}><label className="label">Note</label>
                <textarea className="textarea" rows={2} value={doc.notes || ''} onChange={(e) => setDoc({ ...doc, notes: e.target.value })} onBlur={() => saveHeader({ notes: doc.notes })} placeholder="Annotazioni libere…" disabled={isLocked} />
              </div>
            </div>

            {/* Righe */}
            <div className="card" style={{ background: '#fff', padding: 16, borderRadius: 10, border: '1px solid var(--rule)' }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
                <div style={{ fontSize: 11, fontWeight: 500, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--ink-3)' }}>
                  Righe ({lines.length})
                </div>
                <div style={{ display: 'flex', gap: 6 }}>
                  <button className="btn btn-ghost btn-sm" onClick={() => setShowNewLine('manual')} disabled={isLocked}>
                    <Icon name="plus" size={12} /> Manuale
                  </button>
                  <button className="btn btn-ghost btn-sm" onClick={() => setShowNewLine('task')} disabled={isLocked}>
                    <Icon name="list-todo" size={12} /> Da task
                  </button>
                  <button className="btn btn-ghost btn-sm" onClick={() => setShowNewLine('time_entry')} disabled={isLocked}>
                    <Icon name="clock" size={12} /> Da time entry
                  </button>
                </div>
              </div>

              {lines.length === 0 ? (
                <div style={{ padding: 30, textAlign: 'center', color: 'var(--ink-3)', fontSize: 13 }}>
                  Nessuna riga. Aggiungine una con i bottoni qui sopra.
                </div>
              ) : (
                <table className="invoices" style={{ marginTop: 4 }}>
                  <thead>
                    <tr>
                      <th style={{ width: 90 }}>Data</th>
                      <th>Descrizione</th>
                      <th style={{ width: 60, textAlign: 'right' }}>Q.tà</th>
                      <th style={{ width: 50 }}>UM</th>
                      <th style={{ width: 80, textAlign: 'right' }}>Prezzo</th>
                      <th style={{ width: 90, textAlign: 'right' }}>Tot.</th>
                      <th style={{ width: 130 }}>Stato</th>
                      <th style={{ width: 50 }}></th>
                    </tr>
                  </thead>
                  <tbody>
                    {lines.map((l) => (
                      <PendingLineRow key={l.id} line={l} pendingId={id} onEdit={() => setEditingLine(l)} onDelete={() => deleteLine(l.id, l)} onNav={onNav} disabled={isLocked} />
                    ))}
                  </tbody>
                </table>
              )}
            </div>
          </div>

          {/* SIDE: Totali + Allegati */}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 12, position: 'sticky', top: 70, alignSelf: 'start' }}>
            <div className="card" style={{ background: '#fff', padding: 14, borderRadius: 10, border: '1px solid var(--rule)' }}>
              <div style={{ fontSize: 11, fontWeight: 500, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--ink-3)', marginBottom: 10 }}>Totali</div>
              <div style={{ display: 'flex', justifyContent: 'space-between', padding: '6px 0', fontSize: 13 }}>
                <span style={{ color: 'var(--ink-2)' }}>Aperto</span>
                <span className="mono" style={{ fontWeight: 600 }}>€ {new Intl.NumberFormat('it-IT', { minimumFractionDigits: 2 }).format(doc.totale_aperto || 0)}</span>
              </div>
              <div style={{ display: 'flex', justifyContent: 'space-between', padding: '6px 0', fontSize: 13, borderBottom: '1px solid var(--rule-2)' }}>
                <span style={{ color: 'var(--ink-3)' }}>Già fatturato</span>
                <span className="mono" style={{ color: 'var(--green)' }}>€ {new Intl.NumberFormat('it-IT', { minimumFractionDigits: 2 }).format(doc.totale_fatturato || 0)}</span>
              </div>
              <div style={{ display: 'flex', justifyContent: 'space-between', padding: '8px 0 2px', fontSize: 14 }}>
                <span style={{ fontWeight: 500 }}>Totale documento</span>
                <span className="mono" style={{ fontWeight: 600 }}>€ {new Intl.NumberFormat('it-IT', { minimumFractionDigits: 2 }).format(doc.totale_documento || 0)}</span>
              </div>
            </div>

            <div className="card" style={{ background: '#fff', padding: 14, borderRadius: 10, border: '1px solid var(--rule)' }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
                <div style={{ fontSize: 11, fontWeight: 500, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--ink-3)' }}>
                  Allegati ({doc.attachments?.length || 0})
                </div>
                <button className="btn btn-ghost btn-sm" onClick={() => fileInputRef.current?.click()} disabled={saving || isLocked}>
                  <Icon name="upload" size={12} /> {saving ? '…' : 'Carica'}
                </button>
                <input ref={fileInputRef} type="file" accept=".png,.jpg,.jpeg,.webp,.pdf,image/png,image/jpeg,image/webp,application/pdf"
                  style={{ display: 'none' }} onChange={(e) => onUploadFile(e.target.files?.[0])} />
              </div>
              {(doc.attachments || []).length === 0 ? (
                <div style={{ fontSize: 12, color: 'var(--ink-3)', padding: '6px 0' }}>Nessun allegato</div>
              ) : (
                <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                  {doc.attachments.map((a) => (
                    <div key={a.id} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, padding: '6px 8px', background: 'var(--paper-2)', borderRadius: 6 }}>
                      <Icon name={(a.mime_type || '').includes('pdf') ? 'file-text' : 'image'} size={13} />
                      <a href={`/api/pending/attachments/${a.id}`} target="_blank" rel="noopener" style={{ flex: 1, color: 'var(--ink)', textDecoration: 'none', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                        {a.original_name}
                      </a>
                      <span style={{ color: 'var(--ink-3)', fontSize: 11 }}>{Math.round((a.size || 0) / 1024)}KB</span>
                      <button className="ia" onClick={() => deleteAttachment(a.id)} title="Elimina"><Icon name="x" size={12} /></button>
                    </div>
                  ))}
                </div>
              )}
              <div style={{ fontSize: 10, color: 'var(--ink-3)', marginTop: 6 }}>PNG/JPG/WebP/PDF · max 5MB</div>
            </div>

            {fatturatePresenti && (
              <div className="card" style={{ background: 'var(--amber-wash)', padding: 10, borderRadius: 8, border: '1px solid #f0d9a8', fontSize: 11.5, color: 'var(--amber)' }}>
                <Icon name="info" size={11} style={{ display: 'inline-block', verticalAlign: '-1px', marginRight: 4 }} />
                Alcune righe sono già fatturate. Modifiche/eliminazioni non aggiornano le fatture esistenti.
              </div>
            )}
          </div>
        </div>
      </div>

      {editingLine && <PendingLineEditModal pendingId={id} line={editingLine} onClose={() => setEditingLine(null)} onSaved={(d) => { setEditingLine(null); setDoc(d); }} />}
      {showNewLine === 'manual' && <PendingLineEditModal pendingId={id} line={null} onClose={() => setShowNewLine(null)} onSaved={(d) => { setShowNewLine(null); setDoc(d); }} />}
      {showNewLine === 'task' && <AddFromTaskModal pendingId={id} clientId={doc.client_id} onClose={() => setShowNewLine(null)} onAdded={(d) => { setShowNewLine(null); setDoc(d); }} />}
      {showNewLine === 'time_entry' && <AddFromTimeEntryModal pendingId={id} clientId={doc.client_id} onClose={() => setShowNewLine(null)} onAdded={(d) => { setShowNewLine(null); setDoc(d); }} />}
      {showConvert && <PendingConvertModal presetClientId={doc.client_id} onClose={() => setShowConvert(false)} onCreated={(invoiceId) => { setShowConvert(false); onNav('invoices/' + invoiceId); }} />}
    </>
  );
}

// ============================================================================
// RIGA — render compatto
// ============================================================================
function PendingLineRow({ line, pendingId, onEdit, onDelete, onNav, disabled }) {
  const totals = (() => {
    const qty = Number(line.quantita) || 0;
    const price = Number(line.prezzo_unitario) || 0;
    const aliq = Number(line.aliquota_iva) || 0;
    const imp = qty * price * (1 - (Number(line.sconto_pct) || 0) / 100);
    return imp * (1 + aliq / 100);
  })();
  const sourceIcon = line.source_type === 'task' ? 'list-todo' : line.source_type === 'time_entry' ? 'clock' : null;
  const links = line.invoice_links || [];
  return (
    <tr onClick={(e) => { if (!e.target.closest('button') && !e.target.closest('a')) onEdit(); }} style={{ cursor: disabled ? 'default' : 'pointer' }}>
      <td data-label="Data" className={'mono ' + (line.line_date ? '' : 'cell-empty')} style={{ fontSize: 12, color: 'var(--ink-2)' }}>{line.line_date && fmtDate(line.line_date)}</td>
      <td data-label="Descrizione">
        <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
          {sourceIcon && <Icon name={sourceIcon} size={11} style={{ color: 'var(--ink-3)' }} />}
          <span>{line.descrizione}</span>
        </div>
        {links.length > 0 && (
          <div style={{ fontSize: 11, color: 'var(--ink-3)', marginTop: 2, display: 'flex', flexWrap: 'wrap', gap: 6 }}>
            {links.map((lk) => (
              <a key={lk.id} onClick={(e) => { e.stopPropagation(); onNav('invoices/' + lk.invoice_id); }}
                 style={{ cursor: 'pointer', color: 'var(--accent-ink)' }}>
                → Fattura {lk.numero_completo} ({lk.quantity_invoiced})
              </a>
            ))}
          </div>
        )}
      </td>
      <td data-label="Q.tà" className="amount mono">{line.quantita}</td>
      <td data-label="UM" className={'mono ' + (line.unita_misura ? '' : 'cell-empty')} style={{ fontSize: 12, color: 'var(--ink-3)' }}>{line.unita_misura || '—'}</td>
      <td data-label="Prezzo" className="amount mono">€ {new Intl.NumberFormat('it-IT', { minimumFractionDigits: 2 }).format(line.prezzo_unitario || 0)}</td>
      <td data-label="Totale" className="amount total mono">€ {new Intl.NumberFormat('it-IT', { minimumFractionDigits: 2 }).format(totals)}</td>
      <td data-label="Stato">{pendingBadge(line.line_status)}</td>
      <td><button className="ia" onClick={(e) => { e.stopPropagation(); onDelete(); }} title="Elimina riga" disabled={disabled}><Icon name="trash-2" size={12} /></button></td>
    </tr>
  );
}

// ============================================================================
// MODAL EDIT/NEW RIGA MANUALE
// ============================================================================
function PendingLineEditModal({ pendingId, line, onClose, onSaved }) {
  const [f, setF] = useState({
    line_date: line?.line_date || new Date().toISOString().slice(0, 10),
    descrizione: line?.descrizione || '',
    quantita: line?.quantita ?? 1,
    unita_misura: line?.unita_misura || 'h',
    prezzo_unitario: line?.prezzo_unitario ?? '',
    sconto_pct: line?.sconto_pct ?? 0,
    aliquota_iva: line?.aliquota_iva ?? 0,
    natura_iva: line?.natura_iva || 'N2.2',
  });
  const [saving, setSaving] = useState(false);
  const [err, setErr] = useState('');
  const set = (k) => (e) => setF({ ...f, [k]: e.target.value });

  const isFatturata = line && (line.line_status === 'fatturato' || line.line_status === 'parzialmente_fatturato');

  const submit = async (e) => {
    e.preventDefault();
    setSaving(true); setErr('');
    try {
      const payload = {
        line_date: f.line_date,
        descrizione: f.descrizione,
        quantita: Number(f.quantita),
        unita_misura: f.unita_misura || null,
        prezzo_unitario: Number(f.prezzo_unitario) || 0,
        sconto_pct: Number(f.sconto_pct) || 0,
        aliquota_iva: Number(f.aliquota_iva) || 0,
        natura_iva: f.natura_iva || null,
      };
      const updated = line
        ? await window.LibroAPI.updatePendingLine(pendingId, line.id, payload)
        : await window.LibroAPI.addPendingLine(pendingId, payload);
      onSaved(updated);
    } catch (ex) { setErr(ex.message); }
    finally { setSaving(false); }
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <form className="modal" onClick={(e) => e.stopPropagation()} onSubmit={submit} style={{ width: 540 }}>
        <div className="modal-head">
          <div>
            <div style={{ fontSize: 11, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.1em' }}>{line ? 'Modifica' : 'Nuova'} riga</div>
            <h2 style={{ fontFamily: 'Fraunces', fontSize: 18, fontWeight: 500, margin: '4px 0 0' }}>Promemoria #{pendingId}</h2>
          </div>
          <button type="button" className="btn btn-ic btn-ghost" onClick={onClose}><Icon name="x" size={14} /></button>
        </div>
        <div className="modal-body">
          {err && <div className="err" style={{ marginBottom: 12 }}><Icon name="alert-circle" size={14} /> {err}</div>}
          {isFatturata && (
            <div style={{ background: 'var(--amber-wash)', color: 'var(--amber)', padding: 8, borderRadius: 6, fontSize: 12, marginBottom: 12 }}>
              <Icon name="info" size={11} style={{ display: 'inline-block', verticalAlign: '-1px', marginRight: 4 }} />
              Riga già fatturata. Le modifiche non aggiorneranno le fatture esistenti.
            </div>
          )}

          <div style={{ display: 'grid', gridTemplateColumns: '120px 1fr', gap: 10 }}>
            <div className="field"><label className="label">Data</label>
              <input className="input" type="date" value={f.line_date} onChange={set('line_date')} />
            </div>
            <div className="field"><label className="label">Descrizione *</label>
              <input className="input" required value={f.descrizione} onChange={set('descrizione')} placeholder="es. Telefonata supporto…" autoFocus />
            </div>
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: '80px 60px 110px 80px 110px', gap: 8 }}>
            <div className="field"><label className="label">Q.tà</label>
              <input className="input mono" type="number" step="0.01" value={f.quantita} onChange={set('quantita')} />
            </div>
            <div className="field"><label className="label">UM</label>
              <input className="input" value={f.unita_misura || ''} onChange={set('unita_misura')} placeholder="h" />
            </div>
            <div className="field"><label className="label">Prezzo €</label>
              <input className="input mono" type="number" step="0.01" value={f.prezzo_unitario} onChange={set('prezzo_unitario')} />
            </div>
            <div className="field"><label className="label">IVA %</label>
              <input className="input mono" type="number" step="0.01" value={f.aliquota_iva} onChange={set('aliquota_iva')} />
            </div>
            <div className="field"><label className="label">Natura</label>
              <input className="input" value={f.natura_iva || ''} onChange={set('natura_iva')} placeholder="N2.2" />
            </div>
          </div>

          <div style={{ marginTop: 4, padding: 8, background: 'var(--paper-2)', borderRadius: 6, fontSize: 12, color: 'var(--ink-2)' }}>
            Totale riga: <strong>€ {new Intl.NumberFormat('it-IT', { minimumFractionDigits: 2 }).format(
              (Number(f.quantita) || 0) * (Number(f.prezzo_unitario) || 0) * (1 - (Number(f.sconto_pct) || 0) / 100) * (1 + (Number(f.aliquota_iva) || 0) / 100)
            )}</strong>
          </div>
        </div>
        <div className="modal-foot">
          <button type="button" className="btn btn-ghost" onClick={onClose}>Annulla</button>
          <div style={{ flex: 1 }} />
          <button className="btn btn-accent" type="submit" disabled={saving}>{saving ? '…' : (line ? 'Salva' : 'Aggiungi')}</button>
        </div>
      </form>
    </div>
  );
}

// ============================================================================
// MODAL "AGGIUNGI DA TASK"
// ============================================================================
function AddFromTaskModal({ pendingId, clientId, presetTaskId, onClose, onAdded }) {
  const [tasks, setTasks] = useState([]);
  const [projects, setProjects] = useState([]);
  const [loading, setLoading] = useState(true);
  const [selected, setSelected] = useState(presetTaskId || null);
  const [q, setQ] = useState('');
  const [adding, setAdding] = useState(false);
  const [err, setErr] = useState('');

  useEffect(() => {
    Promise.all([
      apiP('/api/tasks').catch(() => []),
      apiP('/api/projects').catch(() => []),
    ]).then(([tks, prs]) => {
      const allowed = (prs || []).filter((p) => !clientId || String(p.client_id || '') === String(clientId)).map((p) => p.id);
      setProjects(prs || []);
      setTasks((tks || []).filter((t) => !clientId || allowed.includes(t.project_id)));
      setLoading(false);
    });
  }, [clientId]);

  const projById = useMemo(() => Object.fromEntries(projects.map((p) => [p.id, p])), [projects]);
  const filtered = useMemo(() => {
    if (!q) return tasks;
    const ql = q.toLowerCase();
    return tasks.filter((t) => (t.title || '').toLowerCase().includes(ql));
  }, [tasks, q]);

  const sel = tasks.find((t) => t.id === selected);
  const project = sel ? projById[sel.project_id] : null;
  const defaultRate = project?.hourly_rate || 0;
  // ore default: somma time_entries non ancora aggiunte a un pending né fatturate
  const [hoursPreview, setHoursPreview] = useState(null);
  useEffect(() => {
    if (!sel) { setHoursPreview(null); return; }
    apiP(`/api/tasks/${sel.id}`).then((full) => {
      const tot = (full.time_entries || []).filter((te) => !te.invoice_item_id && !te.pending_line_id).reduce((s, te) => s + (te.duration_seconds || 0), 0);
      setHoursPreview({ seconds: tot, hours: Math.round((tot / 3600) * 100) / 100 });
    }).catch(() => setHoursPreview(null));
  }, [selected]);

  const [hours, setHours] = useState('');
  const [rate, setRate] = useState('');
  useEffect(() => {
    if (sel) {
      setHours(hoursPreview?.hours || '1');
      setRate(defaultRate || '');
    }
  }, [selected, hoursPreview, defaultRate]);

  const submit = async () => {
    if (!sel) { setErr('Seleziona una task'); return; }
    setAdding(true); setErr('');
    try {
      const updated = await window.LibroAPI.addPendingLine(pendingId, {
        descrizione: sel.title,
        quantita: Number(hours) || 1,
        unita_misura: 'h',
        prezzo_unitario: Number(rate) || 0,
        aliquota_iva: 0,
        natura_iva: 'N2.2',
        source_type: 'task',
        source_task_id: sel.id,
      });
      onAdded(updated);
    } catch (ex) { setErr(ex.message); }
    finally { setAdding(false); }
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()} style={{ width: 600 }}>
        <div className="modal-head">
          <div>
            <div style={{ fontSize: 11, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.1em' }}>Aggiungi da task</div>
            <h2 style={{ fontFamily: 'Fraunces', fontSize: 18, fontWeight: 500, margin: '4px 0 0' }}>Promemoria #{pendingId}</h2>
          </div>
          <button type="button" className="btn btn-ic btn-ghost" onClick={onClose}><Icon name="x" size={14} /></button>
        </div>
        <div className="modal-body">
          {err && <div className="err" style={{ marginBottom: 12 }}><Icon name="alert-circle" size={14} /> {err}</div>}

          <div className="field"><label className="label">Cerca task</label>
            <input className="input" autoFocus placeholder="Filtra per titolo…" value={q} onChange={(e) => setQ(e.target.value)} />
          </div>

          {loading ? <div style={{ color: 'var(--ink-3)' }}>Caricamento…</div> : (
            <div style={{ maxHeight: 240, overflowY: 'auto', border: '1px solid var(--rule)', borderRadius: 6 }}>
              {filtered.length === 0 ? <div style={{ padding: 12, color: 'var(--ink-3)', fontSize: 12 }}>Nessuna task disponibile{clientId ? ' per questo cliente' : ''}</div> :
                filtered.map((t) => {
                  const p = projById[t.project_id];
                  return (
                    <div key={t.id} onClick={() => setSelected(t.id)}
                      style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 10px', cursor: 'pointer', background: selected === t.id ? 'var(--accent-wash)' : 'transparent', borderBottom: '1px solid var(--rule-2)' }}>
                      <div style={{ width: 8, height: 8, borderRadius: '50%', background: p?.color || 'var(--ink-3)' }} />
                      <div style={{ flex: 1, minWidth: 0 }}>
                        <div style={{ fontSize: 13, fontWeight: 500 }}>{t.title}</div>
                        <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>{p?.name || '—'}{p?.hourly_rate ? ` · €${p.hourly_rate}/h` : ''}</div>
                      </div>
                    </div>
                  );
                })}
            </div>
          )}

          {sel && (
            <div style={{ marginTop: 12, padding: 10, background: 'var(--paper-2)', borderRadius: 8 }}>
              <div style={{ fontSize: 12, color: 'var(--ink-3)', marginBottom: 6 }}>Riga generata da: <strong>{sel.title}</strong></div>
              {hoursPreview && hoursPreview.hours > 0 && (
                <div style={{ fontSize: 11, color: 'var(--ink-3)', marginBottom: 8 }}>
                  Ore tracciate non fatturate: <strong>{hoursPreview.hours}h</strong>
                </div>
              )}
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
                <div className="field" style={{ marginBottom: 0 }}><label className="label">Ore</label>
                  <input className="input mono" type="number" step="0.01" value={hours} onChange={(e) => setHours(e.target.value)} />
                </div>
                <div className="field" style={{ marginBottom: 0 }}><label className="label">€/ora</label>
                  <input className="input mono" type="number" step="0.01" value={rate} onChange={(e) => setRate(e.target.value)} />
                </div>
              </div>
            </div>
          )}
        </div>
        <div className="modal-foot">
          <button type="button" className="btn btn-ghost" onClick={onClose}>Annulla</button>
          <div style={{ flex: 1 }} />
          <button className="btn btn-accent" onClick={submit} disabled={adding || !sel}>{adding ? '…' : 'Aggiungi riga'}</button>
        </div>
      </div>
    </div>
  );
}

// ============================================================================
// MODAL "AGGIUNGI DA TIME ENTRY"
// ============================================================================
function AddFromTimeEntryModal({ pendingId, clientId, onClose, onAdded }) {
  const [entries, setEntries] = useState([]);
  const [projects, setProjects] = useState([]);
  const [tasks, setTasks] = useState([]);
  const [loading, setLoading] = useState(true);
  const [selected, setSelected] = useState(new Set());
  const [adding, setAdding] = useState(false);
  const [err, setErr] = useState('');

  useEffect(() => {
    Promise.all([
      apiP('/api/time-entries?limit=200').catch(() => []),
      apiP('/api/projects').catch(() => []),
      apiP('/api/tasks').catch(() => []),
    ]).then(([tes, prs, tks]) => {
      setProjects(prs || []);
      setTasks(tks || []);
      const allowedProj = (prs || []).filter((p) => !clientId || String(p.client_id || '') === String(clientId)).map((p) => p.id);
      const taskById = Object.fromEntries((tks || []).map((t) => [t.id, t]));
      const filtered = (Array.isArray(tes) ? tes : []).filter((te) => {
        if (te.invoice_item_id || te.pending_line_id) return false;
        if (!te.duration_seconds) return false;
        const t = taskById[te.task_id];
        if (!t) return false;
        if (clientId && !allowedProj.includes(t.project_id)) return false;
        return true;
      });
      setEntries(filtered);
      setLoading(false);
    });
  }, [clientId]);

  const projById = useMemo(() => Object.fromEntries(projects.map((p) => [p.id, p])), [projects]);
  const taskById = useMemo(() => Object.fromEntries(tasks.map((t) => [t.id, t])), [tasks]);

  const toggle = (id) => {
    const next = new Set(selected);
    if (next.has(id)) next.delete(id); else next.add(id);
    setSelected(next);
  };

  const submit = async () => {
    if (selected.size === 0) { setErr('Seleziona almeno un time entry'); return; }
    setAdding(true); setErr('');
    try {
      let lastDoc = null;
      for (const teId of selected) {
        const te = entries.find((x) => x.id === teId);
        if (!te) continue;
        const t = taskById[te.task_id];
        const p = t ? projById[t.project_id] : null;
        const hours = Math.round((te.duration_seconds / 3600) * 100) / 100;
        const dt = (te.started_at || '').slice(0, 10);
        const desc = `${t?.title || 'Time entry'} · ${dt}`;
        lastDoc = await window.LibroAPI.addPendingLine(pendingId, {
          descrizione: desc,
          quantita: hours,
          unita_misura: 'h',
          prezzo_unitario: p?.hourly_rate || 0,
          aliquota_iva: 0,
          natura_iva: 'N2.2',
          source_type: 'time_entry',
          source_time_entry_id: te.id,
          source_task_id: te.task_id,
          line_date: dt,
        });
      }
      onAdded(lastDoc);
    } catch (ex) { setErr(ex.message); }
    finally { setAdding(false); }
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()} style={{ width: 640 }}>
        <div className="modal-head">
          <div>
            <div style={{ fontSize: 11, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.1em' }}>Aggiungi da time entry</div>
            <h2 style={{ fontFamily: 'Fraunces', fontSize: 18, fontWeight: 500, margin: '4px 0 0' }}>Promemoria #{pendingId}</h2>
          </div>
          <button type="button" className="btn btn-ic btn-ghost" onClick={onClose}><Icon name="x" size={14} /></button>
        </div>
        <div className="modal-body" style={{ maxHeight: '70vh', overflowY: 'auto' }}>
          {err && <div className="err" style={{ marginBottom: 12 }}><Icon name="alert-circle" size={14} /> {err}</div>}
          {loading ? <div style={{ color: 'var(--ink-3)' }}>Caricamento…</div> : entries.length === 0 ? (
            <div style={{ padding: 30, textAlign: 'center', color: 'var(--ink-3)' }}>Nessun time entry disponibile{clientId ? ' per questo cliente' : ''}</div>
          ) : (
            <table className="invoices">
              <thead>
                <tr>
                  <th style={{ width: 30 }}></th>
                  <th>Task</th>
                  <th style={{ width: 100 }}>Data</th>
                  <th style={{ width: 80, textAlign: 'right' }}>Ore</th>
                  <th style={{ width: 80, textAlign: 'right' }}>€/h</th>
                </tr>
              </thead>
              <tbody>
                {entries.map((te) => {
                  const t = taskById[te.task_id];
                  const p = t ? projById[t.project_id] : null;
                  const hours = Math.round((te.duration_seconds / 3600) * 100) / 100;
                  return (
                    <tr key={te.id} onClick={() => toggle(te.id)} style={{ cursor: 'pointer' }}>
                      <td><input type="checkbox" checked={selected.has(te.id)} onChange={() => toggle(te.id)} /></td>
                      <td>
                        <div style={{ fontSize: 13 }}>{t?.title || 'Task ' + te.task_id}</div>
                        <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>{p?.name || '—'}</div>
                      </td>
                      <td className="mono" style={{ fontSize: 12 }}>{(te.started_at || '').slice(0, 10) && fmtDate(te.started_at)}</td>
                      <td className="amount mono">{hours}</td>
                      <td className="amount mono">{p?.hourly_rate ? `€${p.hourly_rate}` : '—'}</td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          )}
        </div>
        <div className="modal-foot">
          <button type="button" className="btn btn-ghost" onClick={onClose}>Annulla</button>
          <div style={{ flex: 1, fontSize: 12, color: 'var(--ink-3)', alignSelf: 'center' }}>{selected.size} selezionati</div>
          <button className="btn btn-accent" onClick={submit} disabled={adding || selected.size === 0}>{adding ? '…' : `Aggiungi ${selected.size}`}</button>
        </div>
      </div>
    </div>
  );
}

// ============================================================================
// MODAL CONVERSIONE → FATTURA (cross-cliente / cross-promemoria)
// ============================================================================
function PendingConvertModal({ presetClientId, clients: clientsProp, onClose, onCreated }) {
  const [clients, setClients] = useState(clientsProp || []);
  const [clientId, setClientId] = useState(presetClientId || '');
  const [docs, setDocs] = useState([]);
  const [loading, setLoading] = useState(false);
  const [selections, setSelections] = useState({}); // { line_id: quantity }
  const [docType, setDocType] = useState('fattura_sdi');
  const [dataEmissione, setDataEmissione] = useState(new Date().toISOString().slice(0, 10));
  const [dataScadenza, setDataScadenza] = useState('');
  const [creating, setCreating] = useState(false);
  const [err, setErr] = useState('');

  useEffect(() => {
    if (!clientsProp) window.LibroAPI.clients().then(setClients).catch(() => {});
  }, []);

  useEffect(() => {
    if (!clientId) { setDocs([]); return; }
    setLoading(true);
    window.LibroAPI.pendingList({ client_id: clientId }).then((list) => {
      setDocs((list || []).filter((d) => d.status !== 'archiviato' && d.status !== 'annullato'));
      setLoading(false);
    }).catch(() => setLoading(false));
  }, [clientId]);

  // Carica righe complete per ogni doc
  const [allLines, setAllLines] = useState([]);
  useEffect(() => {
    if (!docs.length) { setAllLines([]); return; }
    Promise.all(docs.map((d) => window.LibroAPI.pending(d.id))).then((details) => {
      const flat = [];
      details.forEach((d) => {
        (d.lines || []).forEach((l) => {
          if (l.line_status === 'annullato') return;
          if (l.remaining <= 0.0001) return;
          flat.push({ ...l, _doc_title: d.title || `Promemoria #${d.id}` });
        });
      });
      setAllLines(flat);
    });
  }, [docs]);

  const toggleAll = (val) => {
    if (val) {
      const next = {};
      for (const l of allLines) next[l.id] = l.remaining;
      setSelections(next);
    } else setSelections({});
  };
  const setQty = (lineId, q, max) => {
    const next = { ...selections };
    const v = Math.max(0, Math.min(Number(q) || 0, max));
    if (v <= 0) delete next[lineId]; else next[lineId] = v;
    setSelections(next);
  };

  const totals = useMemo(() => {
    let imp = 0, iva = 0;
    for (const l of allLines) {
      const q = selections[l.id] || 0;
      if (q <= 0) continue;
      const i = q * (l.prezzo_unitario || 0) * (1 - (l.sconto_pct || 0) / 100);
      imp += i; iva += i * (l.aliquota_iva || 0) / 100;
    }
    return { imp: Math.round(imp * 100) / 100, iva: Math.round(iva * 100) / 100, tot: Math.round((imp + iva) * 100) / 100 };
  }, [selections, allLines]);

  const submit = async () => {
    const list = Object.entries(selections).map(([lid, q]) => ({ line_id: Number(lid), quantity: Number(q) }));
    if (list.length === 0) { setErr('Seleziona almeno una riga'); return; }
    setCreating(true); setErr('');
    try {
      const r = await window.LibroAPI.convertPendingToInvoice({
        client_id: Number(clientId),
        line_selections: list,
        doc_type: docType,
        data_emissione: dataEmissione,
        data_scadenza: dataScadenza || null,
      });
      onCreated(r.invoice_id);
    } catch (ex) { setErr(ex.message); }
    finally { setCreating(false); }
  };

  const selectedCount = Object.values(selections).filter((q) => q > 0).length;

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()} style={{ width: 720, maxHeight: '90vh' }}>
        <div className="modal-head">
          <div>
            <div style={{ fontSize: 11, color: 'var(--ink-3)', textTransform: 'uppercase', letterSpacing: '0.1em' }}>Crea fattura da promemoria</div>
            <h2 style={{ fontFamily: 'Fraunces', fontSize: 20, fontWeight: 500, margin: '4px 0 0' }}>Seleziona righe</h2>
          </div>
          <button type="button" className="btn btn-ic btn-ghost" onClick={onClose}><Icon name="x" size={14} /></button>
        </div>
        <div className="modal-body" style={{ maxHeight: '70vh', overflowY: 'auto' }}>
          {err && <div className="err" style={{ marginBottom: 12 }}><Icon name="alert-circle" size={14} /> {err}</div>}

          <div className="field">
            <label className="label">Cliente *</label>
            <select className="input" value={clientId} onChange={(e) => { setClientId(e.target.value); setSelections({}); }}>
              <option value="">— scegli cliente —</option>
              {clients.map((c) => <option key={c.id} value={c.id}>{c.name}</option>)}
            </select>
          </div>

          {clientId && (
            <>
              {loading ? <div style={{ color: 'var(--ink-3)', padding: 20 }}>Caricamento righe…</div> :
                allLines.length === 0 ? (
                  <div style={{ padding: 20, textAlign: 'center', color: 'var(--ink-3)' }}>
                    Nessuna riga aperta da fatturare per questo cliente
                  </div>
                ) : (
                  <>
                    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 }}>
                      <div style={{ fontSize: 11, fontWeight: 500, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--ink-3)' }}>
                        Righe disponibili ({allLines.length})
                      </div>
                      <div style={{ display: 'flex', gap: 6 }}>
                        <button className="btn btn-ghost btn-sm" onClick={() => toggleAll(true)}>Seleziona tutte</button>
                        <button className="btn btn-ghost btn-sm" onClick={() => toggleAll(false)}>Pulisci</button>
                      </div>
                    </div>
                    <table className="invoices">
                      <thead>
                        <tr>
                          <th style={{ width: 30 }}></th>
                          <th>Riga</th>
                          <th style={{ width: 70, textAlign: 'right' }}>Residuo</th>
                          <th style={{ width: 90, textAlign: 'right' }}>Da fatturare</th>
                          <th style={{ width: 80, textAlign: 'right' }}>Tot.</th>
                        </tr>
                      </thead>
                      <tbody>
                        {allLines.map((l) => {
                          const q = selections[l.id] || 0;
                          const tot = q * (l.prezzo_unitario || 0) * (1 - (l.sconto_pct || 0) / 100) * (1 + (l.aliquota_iva || 0) / 100);
                          return (
                            <tr key={l.id}>
                              <td><input type="checkbox" checked={q > 0} onChange={(e) => setQty(l.id, e.target.checked ? l.remaining : 0, l.remaining)} /></td>
                              <td>
                                <div style={{ fontSize: 13 }}>{l.descrizione}</div>
                                <div style={{ fontSize: 11, color: 'var(--ink-3)' }}>{l._doc_title} · {l.line_date && fmtDate(l.line_date)} · €{l.prezzo_unitario}</div>
                              </td>
                              <td className="amount mono">{l.remaining} {l.unita_misura || ''}</td>
                              <td className="amount">
                                <input type="number" step="0.01" min="0" max={l.remaining} value={q || ''} onChange={(e) => setQty(l.id, e.target.value, l.remaining)}
                                  className="input mono" style={{ width: 80, padding: '4px 6px', textAlign: 'right' }} />
                              </td>
                              <td className="amount mono">€{new Intl.NumberFormat('it-IT', { minimumFractionDigits: 2 }).format(tot)}</td>
                            </tr>
                          );
                        })}
                      </tbody>
                    </table>

                    <div style={{ marginTop: 16, padding: 12, background: 'var(--paper-2)', borderRadius: 8 }}>
                      <div style={{ fontSize: 11, fontWeight: 500, textTransform: 'uppercase', letterSpacing: '0.08em', color: 'var(--ink-3)', marginBottom: 8 }}>Dati fattura</div>
                      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 10 }}>
                        <div className="field" style={{ marginBottom: 0 }}><label className="label">Tipo</label>
                          <select className="input" value={docType} onChange={(e) => setDocType(e.target.value)}>
                            <option value="fattura_sdi">Fattura</option>
                            <option value="ricevuta_privata">Ricevuta privata</option>
                            <option value="proforma">Pro-forma</option>
                          </select>
                        </div>
                        <div className="field" style={{ marginBottom: 0 }}><label className="label">Data emissione</label>
                          <input className="input" type="date" value={dataEmissione} onChange={(e) => setDataEmissione(e.target.value)} />
                        </div>
                        <div className="field" style={{ marginBottom: 0 }}><label className="label">Scadenza</label>
                          <input className="input" type="date" value={dataScadenza} onChange={(e) => setDataScadenza(e.target.value)} />
                        </div>
                      </div>
                    </div>

                    <div style={{ marginTop: 12, padding: 10, fontSize: 13 }}>
                      <div style={{ display: 'flex', justifyContent: 'space-between' }}><span>Imponibile</span><span className="mono">€{new Intl.NumberFormat('it-IT', { minimumFractionDigits: 2 }).format(totals.imp)}</span></div>
                      <div style={{ display: 'flex', justifyContent: 'space-between', color: 'var(--ink-3)' }}><span>IVA</span><span className="mono">€{new Intl.NumberFormat('it-IT', { minimumFractionDigits: 2 }).format(totals.iva)}</span></div>
                      <div style={{ display: 'flex', justifyContent: 'space-between', fontWeight: 600, marginTop: 4 }}><span>Totale (esc. bollo)</span><span className="mono">€{new Intl.NumberFormat('it-IT', { minimumFractionDigits: 2 }).format(totals.tot)}</span></div>
                    </div>
                  </>
                )}
            </>
          )}
        </div>
        <div className="modal-foot">
          <button type="button" className="btn btn-ghost" onClick={onClose}>Annulla</button>
          <div style={{ flex: 1, fontSize: 12, color: 'var(--ink-3)', alignSelf: 'center' }}>{selectedCount} righe selezionate</div>
          <button className="btn btn-accent" onClick={submit} disabled={creating || selectedCount === 0 || !clientId}>{creating ? '…' : 'Crea bozza fattura'}</button>
        </div>
      </div>
    </div>
  );
}

window.PendingScreen = PendingScreen;
window.PendingNewForm = PendingNewForm;
window.PendingConvertModal = PendingConvertModal;
window.AddFromTaskModal = AddFromTaskModal;
