// Invoice manager — landing page that lists all saved invoices. Mirrors the
// shot-list projects manager: subheader, 4-tab filter (All / Favourites /
// Archived / Deleted) and a design-system table. Action buttons per row:
// duplicate, archive/unarchive, trash (or restore + permanent delete in
// the Deleted tab). Clicking a row opens the editor at ?id=<uuid>.

const { useState: useStateM, useEffect: useEffectM } = React;

function fmtRelativeInv(ts) {
  if (!ts) return '';
  const diff = Date.now() - ts;
  const sec = Math.floor(diff / 1000);
  if (sec < 60) return 'just now';
  const min = Math.floor(sec / 60);
  if (min < 60) return `${min}m ago`;
  const hr = Math.floor(min / 60);
  if (hr < 24) return `${hr}h ago`;
  const day = Math.floor(hr / 24);
  if (day < 7) return `${day}d ago`;
  if (day < 30) return `${Math.floor(day / 7)}w ago`;
  return new Date(ts).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });
}
function fmtInvTrashCountdown(deletedAt) {
  const remaining = INVOICE_TRASH_TTL_MS - (Date.now() - deletedAt);
  if (remaining <= 0) return { label: 'expiring…', level: 'danger' };
  const days = Math.ceil(remaining / (24 * 60 * 60 * 1000));
  let level = 'ok';
  if (days <= 3) level = 'danger';
  else if (days <= 7) level = 'urgent';
  return { label: `in ${days} day${days === 1 ? '' : 's'}`, level };
}

function InvoiceManager() {
  const [theme, setTheme] = useStateM(() => document.documentElement.getAttribute('data-theme') || 'dark');
  const [railExpanded, setRailExpanded] = useStateM(false);
  const [filter, setFilter] = useStateM('all');     // all | archived | deleted
  const [all, setAll] = useStateM(() => loadInvoiceIndex() || []);

  useEffectM(() => { document.documentElement.setAttribute('data-theme', theme); }, [theme]);
  useEffectM(() => { document.title = 'Invoices — Pixel Portal'; }, []);

  const refresh = () => setAll(loadInvoiceIndex() || []);

  // ── Derived data ────────────────────────────────────────────────
  const active = all.filter(m => !m.deletedAt);
  const counts = {
    all: active.filter(m => !m.archived).length,
    archived: active.filter(m => m.archived).length,
    deleted: all.filter(m => m.deletedAt).length,
  };

  let list;
  if (filter === 'archived')      list = active.filter(m => m.archived);
  else if (filter === 'deleted')  list = all.filter(m => m.deletedAt);
  else                            list = active.filter(m => !m.archived);

  list = [...list].sort((a, b) => {
    if (filter === 'deleted') return (b.deletedAt || 0) - (a.deletedAt || 0);
    return (b.updatedAt || 0) - (a.updatedAt || 0);
  });

  // ── Actions ────────────────────────────────────────────────
  const onNew = () => {
    const id = createInvoice();
    location.href = `${location.pathname}?id=${encodeURIComponent(id)}`;
  };
  const onOpen = (m) => {
    if (m.deletedAt) return;
    location.href = `${location.pathname}?id=${encodeURIComponent(m.id)}`;
  };
  const onToggleArchive = (m) => {
    const idx = loadInvoiceIndex() || [];
    const e = idx.find(x => x.id === m.id);
    if (e) { e.archived = !e.archived; saveInvoiceIndex(idx); refresh(); }
  };
  const onDuplicate = (m) => {
    const newId = duplicateInvoiceStorage(m.id);
    if (newId) refresh();
  };
  const onTrash = (m) => { trashInvoice(m.id); refresh(); };
  const onRestore = (m) => { restoreInvoice(m.id); refresh(); };
  const onPurge = (m) => {
    const noun = m.mode === 'quote' ? 'quote' : 'invoice';
    const label = `${noun} #${m.number || ''}`.trim();
    if (!confirm(`Delete ${label} forever? This cannot be undone.`)) return;
    deleteInvoiceStorage(m.id);
    refresh();
  };

  // ── Render ────────────────────────────────────────────────
  return (
    <div className={`app ${railExpanded ? 'rail-expanded' : ''}`} data-screen-label="Invoices">
      <Rail page="invoice" expanded={railExpanded} setExpanded={setRailExpanded} />
      <main className="main">
        <Header theme={theme} setTheme={setTheme} crumbs={[]} />

        <div className="subheader">
          <div className="subheader-left">
            <div className="subheader-eyebrow"><span className="dot" /> Tool</div>
            <h1>Invoices</h1>
            {all.length > 0 && (
              <div className="subheader-meta">
                <span><strong>{active.length}</strong> invoice{active.length === 1 ? '' : 's'}</span>
                {counts.deleted > 0 && (
                  <>
                    <span className="sep">·</span>
                    <span><strong>{counts.deleted}</strong> in trash</span>
                  </>
                )}
              </div>
            )}
          </div>
          <div className="subheader-right">
            <button className="btn btn-primary" onClick={onNew}><IconPlus /> New invoice</button>
          </div>
        </div>

        <div className="toolbar">
          <div className="seg" role="group" aria-label="Filter">
            <button className={filter === 'all' ? 'active' : ''} onClick={() => setFilter('all')}>
              All <span className="filter-count">{counts.all}</span>
            </button>
            <button className={filter === 'archived' ? 'active' : ''} onClick={() => setFilter('archived')}>
              <IconArchive /> Archived <span className="filter-count">{counts.archived}</span>
            </button>
            <button className={filter === 'deleted' ? 'active' : ''} onClick={() => setFilter('deleted')}>
              <IconTrash /> Deleted <span className="filter-count">{counts.deleted}</span>
            </button>
          </div>
          <div className="toolbar-spacer" />
        </div>

        <div className="scroll">
          {all.length === 0 ? (
            <div className="empty-state" style={{ paddingTop: 100 }}>
              <h2 style={{ fontFamily: 'var(--font-display)', fontSize: 22, fontWeight: 600, color: 'var(--text)', margin: '0 0 8px' }}>
                No invoices yet
              </h2>
              <p style={{ fontSize: 14, color: 'var(--text-3)', marginBottom: 24 }}>
                Create your first invoice to get started.
              </p>
              <button className="btn btn-primary" onClick={onNew}><IconPlus /> New invoice</button>
            </div>
          ) : list.length === 0 ? (
            <div className="empty-state">No invoices match this filter.</div>
          ) : (
            <div className="table-wrap" style={{ marginTop: 4 }}>
              <table className="table">
                <thead>
                  <tr>
                    <th style={{ width: 110, paddingLeft: 22 }}>Number</th>
                    <th>Client</th>
                    <th style={{ width: 150 }}>{filter === 'deleted' ? 'Expires' : 'Date'}</th>
                    <th style={{ width: 130, textAlign: 'right' }}>Amount</th>
                    <th style={{ width: 160 }}></th>
                  </tr>
                </thead>
                <tbody>
                  {list.map(m => (
                    <InvoiceRow
                      key={m.id}
                      meta={m}
                      isTrashed={!!m.deletedAt}
                      onOpen={onOpen}
                      onToggleArchive={onToggleArchive}
                      onDuplicate={onDuplicate}
                      onTrash={onTrash}
                      onRestore={onRestore}
                      onPurge={onPurge}
                    />
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>
      </main>
    </div>
  );
}

function InvoiceRow({ meta: m, isTrashed, onOpen, onToggleArchive, onDuplicate, onTrash, onRestore, onPurge }) {
  const cls = [
    'tbl-row',
    isTrashed ? 'is-trashed' : '',
    m.archived ? 'is-archived' : '',
  ].filter(Boolean).join(' ');

  const onRowClick = (e) => {
    if (e.target.closest('button')) return;
    onOpen(m);
  };

  return (
    <tr
      className={cls}
      onClick={onRowClick}
      style={{ cursor: isTrashed ? 'default' : 'pointer', opacity: isTrashed ? 0.7 : m.archived ? 0.65 : 1 }}
    >
      <td style={{ paddingLeft: 22 }}>
        {isTrashed && (
          <span title="In trash" style={{ marginRight: 8, verticalAlign: 'middle', color: 'var(--text-4)', display: 'inline-flex' }}>
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" width="14" height="14"><path d="M4 7h16M9 7V5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2"/><path d="M6 7l1 13a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-13"/></svg>
          </span>
        )}
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12.5, color: 'var(--text)', fontWeight: 600, letterSpacing: '0.02em' }}>
          {m.number ? `#${m.number}` : '—'}
        </span>
        {m.mode === 'quote' && (
          <span style={{
            marginLeft: 8, padding: '2px 6px', borderRadius: 4,
            background: 'var(--accent-soft)', color: 'var(--accent)',
            fontSize: 10, fontWeight: 600, letterSpacing: '0.05em', textTransform: 'uppercase',
          }}>quote</span>
        )}
        {m.paid && m.mode !== 'quote' && (
          <span style={{
            marginLeft: 8, padding: '2px 6px', borderRadius: 4,
            background: 'rgba(91,214,140,0.18)', color: 'var(--status-approved)',
            fontSize: 10, fontWeight: 600, letterSpacing: '0.05em', textTransform: 'uppercase',
          }}>paid</span>
        )}
      </td>
      <td>
        <span style={{ color: m.clientName ? 'var(--text)' : 'var(--text-4)', fontSize: 13.5, fontWeight: m.clientName ? 500 : 400 }}>
          {m.clientName || '— No client —'}
        </span>
      </td>
      <td style={{ color: 'var(--text-3)', fontSize: 12.5, fontFamily: 'var(--font-mono)' }}>
        {isTrashed
          ? (() => {
              const cd = fmtInvTrashCountdown(m.deletedAt);
              const color = cd.level === 'danger' ? '#f87171' : cd.level === 'urgent' ? 'var(--status-review)' : 'var(--text-3)';
              return <span style={{ color }}>Auto-deletes {cd.label}</span>;
            })()
          : (m.date ? fmtDate(m.date, 'US') : fmtRelativeInv(m.updatedAt || m.createdAt))}
      </td>
      <td style={{ textAlign: 'right', color: 'var(--text)', fontSize: 13.5, fontVariantNumeric: 'tabular-nums', fontFamily: 'var(--font-mono)', fontWeight: 600 }}>
        {fmtMoney(m.total || 0, m.currency || 'USD')}
      </td>
      <td onClick={(e) => e.stopPropagation()}>
        <div className="col-actions-inner" style={{ justifyContent: 'flex-end' }}>
          {isTrashed ? (
            <>
              <button className="icon-btn" title="Restore" onClick={() => onRestore(m)}>
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" width="16" height="16">
                  <path d="M3 12a9 9 0 1 0 3-6.7" />
                  <path d="M3 4v5h5" />
                </svg>
              </button>
              <button className="icon-btn" title="Delete forever" onClick={() => onPurge(m)}>
                <IconTrash />
              </button>
            </>
          ) : (
            <>
              <button className="icon-btn" title="Duplicate" onClick={() => onDuplicate(m)}>
                <IconDuplicate />
              </button>
              <button className="icon-btn" title={m.archived ? 'Unarchive' : 'Archive'} onClick={() => onToggleArchive(m)}>
                <IconArchive />
              </button>
              <button className="icon-btn" title="Move to trash" onClick={() => onTrash(m)}>
                <IconTrash />
              </button>
            </>
          )}
        </div>
      </td>
    </tr>
  );
}

// Archive icon — not in icons.jsx, defined locally.
const IconArchive = (props) => (
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...props}>
    <rect x="3" y="4" width="18" height="4" rx="1" />
    <path d="M5 8v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8" />
    <path d="M10 12h4" />
  </svg>
);

window.InvoiceManager = InvoiceManager;
