// view-billing.jsx — Client billing & invoicing. Turns approved/billable
// hours into per-client invoices at each client's contract bill rate, with
// margin (billed vs. labor cost), AR aging, and an invoice detail drawer.

function BillingView() {
  const { clients, jobs, timecards, employees, toast } = useAdmin();
  const [invoiceDrawer, setInvoiceDrawer] = useState(null);
  const [posted, setPosted] = useState(() => RFP.posting.listInvoices());
  const [journalView, setJournalView] = useState(null);
  const [autoPost, setAutoPost] = useState(true);

  const refreshPosted = () => setPosted(RFP.posting.listInvoices());

  // ── Build billing rows per client from this period's timecards ──
  // A card is "billable" once it reaches accounting or is approved.
  const billable = timecards.filter(t => t.status === 'pending-acct' || t.status === 'approved');

  const byClient = {};
  for (const t of billable) {
    const job = jobs.find(j => j.id === t.jobId);
    const cl = clients.find(c => c.id === job?.clientId);
    if (!cl || !job) continue;
    byClient[cl.id] = byClient[cl.id] || { client: cl, jobs: {}, hours: 0, billed: 0, cost: 0 };
    const e = employees.find(x => x.id === t.employeeId);
    const billed = t.total * cl.billRate;
    const cost = t.regular * (e?.baseRate || 0) + t.overtime * (e?.baseRate || 0) * 1.5;
    byClient[cl.id].hours += t.total;
    byClient[cl.id].billed += billed;
    byClient[cl.id].cost += cost;
    byClient[cl.id].jobs[job.id] = byClient[cl.id].jobs[job.id] || { job, hours: 0, billed: 0 };
    byClient[cl.id].jobs[job.id].hours += t.total;
    byClient[cl.id].jobs[job.id].billed += billed;
  }
  const clientRows = Object.values(byClient).sort((a, b) => b.billed - a.billed);

  const totalBillable = clientRows.reduce((s, r) => s + r.billed, 0);
  const totalCost = clientRows.reduce((s, r) => s + r.cost, 0);
  const margin = totalBillable - totalCost;
  const marginPct = totalBillable ? (margin / totalBillable) * 100 : 0;

  // ── Existing invoices (AR ledger) ──
  const INVOICES = [
    { id: 'INV-2026-0188', clientId: 'cli-bnsf', period: '05-04 → 05-17', amount: 18606.38, issued: '2026-05-19', due: '2026-06-18', status: 'sent' },
    { id: 'INV-2026-0185', clientId: 'cli-uprr', period: '05-04 → 05-17', amount: 12344.30, issued: '2026-05-19', due: '2026-06-18', status: 'sent' },
    { id: 'INV-2026-0179', clientId: 'cli-csx',  period: '04-20 → 05-03', amount: 9870.00,  issued: '2026-05-05', due: '2026-06-19', status: 'sent' },
    { id: 'INV-2026-0172', clientId: 'cli-bnsf', period: '04-20 → 05-03', amount: 21450.75, issued: '2026-05-05', due: '2026-06-04', status: 'paid' },
    { id: 'INV-2026-0166', clientId: 'cli-uprr', period: '04-06 → 04-19', amount: 14210.00, issued: '2026-04-21', due: '2026-05-21', status: 'overdue' },
  ];
  const arOutstanding = INVOICES.filter(i => i.status !== 'paid').reduce((s, i) => s + i.amount, 0);
  const arOverdue = INVOICES.filter(i => i.status === 'overdue').reduce((s, i) => s + i.amount, 0);

  const invCols = [
    { key: 'id', label: 'Invoice #', mono: true },
    { key: 'client', label: 'Client', render: (r) => clients.find(c => c.id === r.clientId)?.name || '—' },
    { key: 'period', label: 'Period', mono: true },
    { key: 'issued', label: 'Issued', mono: true },
    { key: 'due', label: 'Due', mono: true },
    { key: 'amount', label: 'Amount', align: 'right', mono: true, render: (r) => A_fmtCurrency(r.amount) },
    { key: 'status', label: 'Status', render: (r) => {
      const tone = { paid: 'good', sent: 'info', overdue: 'bad', draft: 'neutral' }[r.status];
      return <Pill tone={tone}>{r.status}</Pill>;
    } },
  ];

  return (
    <>
      {/* Auto-post control bar */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 14, background: '#0F172A', color: '#fff', borderRadius: 12, padding: '14px 18px', marginBottom: 18 }}>
        <div style={{ width: 40, height: 40, borderRadius: 10, background: 'rgba(255,255,255,0.1)', display: 'grid', placeItems: 'center' }}><IconBuilding size={20} /></div>
        <div style={{ flex: 1 }}>
          <div style={{ fontWeight: 700, fontSize: 14.5 }}>Automatic invoice posting</div>
          <div style={{ fontSize: 12.5, color: 'rgba(255,255,255,0.6)' }}>When a pay period closes, generate every client invoice, post the GL journal entry, and push to QuickBooks Online.</div>
        </div>
        <button onClick={() => setAutoPost(a => !a)} style={{ display: 'flex', alignItems: 'center', gap: 8, background: 'transparent', border: 'none', cursor: 'pointer', color: '#fff' }}>
          <span style={{ width: 42, height: 24, borderRadius: 12, background: autoPost ? 'var(--good)' : 'rgba(255,255,255,0.2)', position: 'relative', transition: 'background 160ms' }}>
            <span style={{ position: 'absolute', top: 3, left: autoPost ? 21 : 3, width: 18, height: 18, borderRadius: 9, background: '#fff', transition: 'left 160ms' }} />
          </span>
          <span style={{ fontSize: 12.5, fontWeight: 600 }}>{autoPost ? 'On' : 'Off'}</span>
        </button>
        <Button variant="primary" size="md" icon={<IconUpload size={14} />} onClick={() => {
          if (clientRows.length === 0) { toast('No billable hours to post', 'info'); return; }
          const res = RFP.posting.postBatch(clientRows, { glTarget: 'QuickBooks Online' });
          refreshPosted();
          toast(`${res.count} invoices posted · ${A_fmtCurrency(res.total)} · GL journals created`, 'success');
        }}>Run auto-post now</Button>
      </div>

      {/* KPIs */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 14, marginBottom: 22 }}>
        <KPI label="Billable this period" value={A_fmtCurrency(totalBillable)} sub="approved + in review" tone="accent" icon={<IconDollar size={16} />} />
        <KPI label="Gross margin" value={`${marginPct.toFixed(1)}%`} sub={A_fmtCurrency(margin)} tone={marginPct > 45 ? 'good' : 'warn'} icon={<IconBuilding size={16} />} />
        <KPI label="AR outstanding" value={A_fmtCurrency(arOutstanding)} sub="unpaid invoices" tone="neutral" icon={<IconClipboard size={16} />} />
        <KPI label="Overdue" value={A_fmtCurrency(arOverdue)} sub="past due date" tone={arOverdue > 0 ? 'bad' : 'good'} icon={<IconAlert size={16} />} />
      </div>

      {/* Ready to invoice */}
      <AdminSection title="Ready to invoice · this period"
        action={<Button variant="primary" size="sm" icon={<IconClipboard size={12} />} onClick={() => {
          if (clientRows.length === 0) { toast('No billable hours yet', 'info'); return; }
          const res = RFP.posting.postBatch(clientRows, { glTarget: 'QuickBooks Online' });
          refreshPosted();
          toast(`${res.count} invoices posted to GL · ${A_fmtCurrency(res.total)}`, 'success');
        }}>Post all now</Button>}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          {clientRows.length === 0 && (
            <div style={{ padding: 28, textAlign: 'center', color: 'var(--muted-2)', background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 12 }}>
              No billable hours yet — approve timecards to populate.
            </div>
          )}
          {clientRows.map(r => {
            const m = r.billed - r.cost;
            const mp = r.billed ? (m / r.billed) * 100 : 0;
            return (
              <div key={r.client.id} style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 12, padding: '14px 18px' }}>
                <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr 1fr 1fr auto', gap: 16, alignItems: 'center' }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                    <div style={{ width: 40, height: 40, borderRadius: 9, background: 'var(--text)', color: '#fff', display: 'grid', placeItems: 'center', fontSize: 11, fontWeight: 700, fontFamily: 'var(--font-mono)' }}>{r.client.railroad}</div>
                    <div>
                      <div style={{ fontWeight: 700, fontSize: 14 }}>{r.client.name}</div>
                      <div style={{ fontSize: 11.5, color: 'var(--muted)' }}>{Object.keys(r.jobs).length} job{Object.keys(r.jobs).length === 1 ? '' : 's'} · {r.client.terms} · {A_fmtCurrency(r.client.billRate)}/hr</div>
                    </div>
                  </div>
                  <div>
                    <div className="eyebrow" style={{ fontSize: 9.5 }}>HOURS</div>
                    <div className="mono" style={{ fontSize: 16, fontWeight: 700 }}>{A_fmtNum(r.hours, 1)}</div>
                  </div>
                  <div>
                    <div className="eyebrow" style={{ fontSize: 9.5 }}>BILLABLE</div>
                    <div className="mono" style={{ fontSize: 16, fontWeight: 700, color: 'var(--accent)' }}>{A_fmtCurrency(r.billed)}</div>
                  </div>
                  <div>
                    <div className="eyebrow" style={{ fontSize: 9.5 }}>MARGIN</div>
                    <div className="mono" style={{ fontSize: 16, fontWeight: 700, color: mp > 45 ? 'var(--good)' : 'var(--warn)' }}>{mp.toFixed(0)}%</div>
                  </div>
                  <Button variant="secondary" size="sm" iconRight={<IconChevronRight size={12} />} onClick={() => setInvoiceDrawer(r)}>Preview invoice</Button>
                </div>
              </div>
            );
          })}
        </div>
      </AdminSection>

      {/* Posted invoices + GL journal (this session) */}
      {posted.length > 0 && (
        <AdminSection title={`Posted this session (${posted.length})`}
          action={<Button variant="ghost" size="sm" icon={<IconDownload size={12} />} onClick={() => {
            const rows = [['Invoice','Client','Period','Hours','Total','GL Ref','GL Status'], ...posted.map(i => [i.id, i.clientName, i.period, i.hours, i.total.toFixed(2), i.glRef||'', i.glStatus])];
            const csv = rows.map(r => r.join(',')).join('\n');
            if (typeof downloadBlob === 'function') downloadBlob('posted-invoices.csv', csv, 'text/csv');
            toast('Posted invoice register exported', 'success');
          }}>Export register</Button>}>
          <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 12, overflow: 'hidden' }}>
            <div style={{ display: 'grid', gridTemplateColumns: '1.1fr 1.4fr 1fr 0.8fr 1fr 1fr 90px', gap: 10, padding: '10px 16px', background: 'var(--panel-2)', borderBottom: '1px solid var(--line)', fontSize: 10.5, fontWeight: 600, letterSpacing: 0.5, textTransform: 'uppercase', color: 'var(--muted)' }}>
              <span>Invoice</span><span>Client</span><span>GL journal</span><span style={{ textAlign: 'right' }}>Total</span><span>GL ref</span><span>GL status</span><span></span>
            </div>
            {posted.map((inv, i) => (
              <div key={inv.id} style={{ display: 'grid', gridTemplateColumns: '1.1fr 1.4fr 1fr 0.8fr 1fr 1fr 90px', gap: 10, padding: '11px 16px', borderTop: i === 0 ? 'none' : '1px solid var(--line)', alignItems: 'center' }}>
                <span className="mono" style={{ fontSize: 12, fontWeight: 600 }}>{inv.id}</span>
                <span style={{ fontSize: 13 }}>{inv.clientName}</span>
                <span className="mono" style={{ fontSize: 11.5, color: 'var(--muted)' }}>{inv.journalId}</span>
                <span className="mono" style={{ textAlign: 'right', fontSize: 12.5, fontWeight: 700 }}>{A_fmtCurrency(inv.total)}</span>
                <span className="mono" style={{ fontSize: 11.5 }}>{inv.glRef || '—'}</span>
                <span>{inv.glStatus === 'posted' ? <Pill tone="good"><IconCheck size={10} /> posted</Pill> : <Pill tone="bad">error</Pill>}</span>
                <span style={{ textAlign: 'right' }}><button onClick={() => setJournalView(RFP.posting.getJournal(inv.id))} style={{ background: 'var(--panel)', border: '1px solid var(--line-strong)', borderRadius: 8, padding: '5px 10px', fontSize: 11.5, fontWeight: 600, color: 'var(--text-2)', cursor: 'pointer' }}>Journal</button></span>
              </div>
            ))}
          </div>
        </AdminSection>
      )}

      {/* AR ledger */}
      <AdminSection title="Invoice ledger · accounts receivable"
        action={<Button variant="ghost" size="sm" icon={<IconDownload size={12} />} onClick={() => toast('AR aging report exported', 'success')}>AR aging</Button>}>
        <DataTable columns={invCols} rows={INVOICES} />
      </AdminSection>

      {/* Invoice preview drawer */}
      <Drawer open={!!invoiceDrawer} onClose={() => setInvoiceDrawer(null)}
        eyebrow="DRAFT INVOICE" title={invoiceDrawer?.client.name || ''} width={620}
        footer={invoiceDrawer && (
          <>
            <Button variant="secondary" onClick={() => setInvoiceDrawer(null)}>Close</Button>
            <Button variant="secondary" icon={<IconDownload size={14} />} onClick={() => { toast('Invoice PDF downloaded', 'success'); }}>Download PDF</Button>
            <Button variant="primary" icon={<IconUpload size={14} />} onClick={() => {
              const res = RFP.posting.post(invoiceDrawer, { glTarget: 'QuickBooks Online' });
              refreshPosted();
              toast(`${res.invoice.id} posted · GL ${res.journal.id} · pushed to QuickBooks`, 'success');
              setInvoiceDrawer(null);
            }}>Post &amp; send</Button>
          </>
        )}>
        {invoiceDrawer && <InvoicePreview row={invoiceDrawer} />}
      </Drawer>

      {/* GL journal entry drawer */}
      <Drawer open={!!journalView} onClose={() => setJournalView(null)}
        eyebrow="GENERAL LEDGER" title={journalView ? journalView.id : ''} width={560}
        footer={<Button variant="secondary" onClick={() => setJournalView(null)}>Close</Button>}>
        {journalView && <JournalEntry je={journalView} />}
      </Drawer>
    </>
  );
}

// ── GL journal entry detail ──────────────────────────────────
function JournalEntry({ je }) {
  return (
    <div>
      <div style={{ fontSize: 12.5, color: 'var(--muted)', marginBottom: 4 }}>{je.memo}</div>
      <div className="mono" style={{ fontSize: 11.5, color: 'var(--muted-2)', marginBottom: 16 }}>Date {je.date} · Invoice {je.invoiceId}</div>
      <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 10, overflow: 'hidden' }}>
        <div style={{ display: 'grid', gridTemplateColumns: '70px 1fr 100px 100px', gap: 10, padding: '10px 14px', background: 'var(--panel-2)', borderBottom: '1px solid var(--line)', fontSize: 10.5, fontWeight: 600, letterSpacing: 0.5, textTransform: 'uppercase', color: 'var(--muted)' }}>
          <span>Acct</span><span>Account</span><span style={{ textAlign: 'right' }}>Debit</span><span style={{ textAlign: 'right' }}>Credit</span>
        </div>
        {je.lines.map((l, i) => (
          <div key={i} style={{ display: 'grid', gridTemplateColumns: '70px 1fr 100px 100px', gap: 10, padding: '11px 14px', borderTop: i === 0 ? 'none' : '1px solid var(--line)', alignItems: 'center' }}>
            <span className="mono" style={{ fontSize: 12, fontWeight: 600 }}>{l.account}</span>
            <span style={{ fontSize: 13 }}>{l.name}</span>
            <span className="mono" style={{ textAlign: 'right', fontSize: 12.5, color: l.debit ? 'var(--text)' : 'var(--muted-2)' }}>{l.debit ? A_fmtCurrency(l.debit) : '—'}</span>
            <span className="mono" style={{ textAlign: 'right', fontSize: 12.5, color: l.credit ? 'var(--text)' : 'var(--muted-2)' }}>{l.credit ? A_fmtCurrency(l.credit) : '—'}</span>
          </div>
        ))}
        <div style={{ display: 'grid', gridTemplateColumns: '70px 1fr 100px 100px', gap: 10, padding: '11px 14px', borderTop: '2px solid var(--text)', background: 'var(--panel-2)', alignItems: 'center', fontWeight: 700 }}>
          <span></span><span style={{ fontSize: 12.5 }}>Totals</span>
          <span className="mono" style={{ textAlign: 'right', fontSize: 12.5 }}>{A_fmtCurrency(je.debits)}</span>
          <span className="mono" style={{ textAlign: 'right', fontSize: 12.5 }}>{A_fmtCurrency(je.credits)}</span>
        </div>
      </div>
      <div style={{ marginTop: 14, padding: '11px 14px', borderRadius: 8, background: je.balanced ? 'var(--good-soft)' : 'var(--bad-soft)', color: je.balanced ? 'var(--good)' : 'var(--bad)', fontSize: 13, fontWeight: 600, display: 'flex', alignItems: 'center', gap: 8 }}>
        {je.balanced ? <><IconCheck size={15} /> Balanced — debits equal credits. Posted to QuickBooks Online.</> : <><IconAlert size={15} /> Out of balance — not posted.</>}
      </div>
    </div>
  );
}

function InvoicePreview({ row }) {
  const { tweaks } = useTweakValues();
  const jobRows = Object.values(row.jobs);
  const subtotal = row.billed;
  const tax = 0; // services — typically no sales tax on rail flagging labor
  return (
    <div>
      {/* Invoice header */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 20, paddingBottom: 16, borderBottom: '2px solid var(--text)' }}>
        <div>
          <div style={{ fontWeight: 800, fontSize: 18, letterSpacing: -0.3 }}>{tweaks?.companyName || 'RailFlagsPro'}</div>
          <div style={{ fontSize: 11.5, color: 'var(--muted)', marginTop: 2 }}>RWIC Field Operations · EIN 84-•••••••</div>
        </div>
        <div style={{ textAlign: 'right' }}>
          <div className="eyebrow">INVOICE</div>
          <div className="mono" style={{ fontSize: 15, fontWeight: 700 }}>DRAFT</div>
          <div style={{ fontSize: 11.5, color: 'var(--muted)', marginTop: 2 }}>Period 05-18 → 05-31</div>
        </div>
      </div>

      {/* Bill to */}
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 18 }}>
        <div>
          <div className="eyebrow" style={{ marginBottom: 4 }}>BILL TO</div>
          <div style={{ fontWeight: 700, fontSize: 14 }}>{row.client.name}</div>
          <div style={{ fontSize: 12, color: 'var(--muted)' }}>{row.client.railroad} · Accounts Payable</div>
          <div style={{ fontSize: 12, color: 'var(--muted)' }}>Terms: {row.client.terms}</div>
        </div>
        <div style={{ textAlign: 'right' }}>
          <div className="eyebrow" style={{ marginBottom: 4 }}>CONTRACT RATE</div>
          <div className="mono" style={{ fontSize: 14, fontWeight: 700 }}>{A_fmtCurrency(row.client.billRate)}/hr</div>
        </div>
      </div>

      {/* Line items by job */}
      <div style={{ background: 'var(--panel)', border: '1px solid var(--line)', borderRadius: 10, overflow: 'hidden', marginBottom: 16 }}>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 80px 90px 110px', gap: 10, padding: '10px 14px', background: 'var(--panel-2)', borderBottom: '1px solid var(--line)', fontSize: 10.5, fontWeight: 600, letterSpacing: 0.5, textTransform: 'uppercase', color: 'var(--muted)' }}>
          <span>Project</span><span style={{ textAlign: 'right' }}>Hours</span><span style={{ textAlign: 'right' }}>Rate</span><span style={{ textAlign: 'right' }}>Amount</span>
        </div>
        {jobRows.map((jr, i) => (
          <div key={jr.job.id} style={{ display: 'grid', gridTemplateColumns: '1fr 80px 90px 110px', gap: 10, padding: '11px 14px', borderTop: i === 0 ? 'none' : '1px solid var(--line)', alignItems: 'center' }}>
            <div>
              <div style={{ fontSize: 13, fontWeight: 600 }}>{jr.job.name}</div>
              <div className="mono" style={{ fontSize: 10.5, color: 'var(--muted)' }}>{jr.job.projectNumber} · MP {jr.job.mp}</div>
            </div>
            <span className="mono" style={{ textAlign: 'right', fontSize: 12.5 }}>{A_fmtNum(jr.hours, 1)}</span>
            <span className="mono" style={{ textAlign: 'right', fontSize: 12.5, color: 'var(--muted)' }}>{A_fmtCurrency(row.client.billRate)}</span>
            <span className="mono" style={{ textAlign: 'right', fontSize: 12.5, fontWeight: 600 }}>{A_fmtCurrency(jr.billed)}</span>
          </div>
        ))}
      </div>

      {/* Totals */}
      <div style={{ marginLeft: 'auto', width: 260 }}>
        {[['Subtotal', subtotal], ['Tax (services)', tax]].map(([k, v]) => (
          <div key={k} style={{ display: 'flex', justifyContent: 'space-between', padding: '6px 0', fontSize: 13 }}>
            <span style={{ color: 'var(--muted)' }}>{k}</span>
            <span className="mono">{A_fmtCurrency(v)}</span>
          </div>
        ))}
        <div style={{ display: 'flex', justifyContent: 'space-between', padding: '10px 0', marginTop: 4, borderTop: '2px solid var(--text)', fontSize: 16, fontWeight: 700 }}>
          <span>Total due</span>
          <span className="mono">{A_fmtCurrency(subtotal + tax)}</span>
        </div>
      </div>

      <div style={{ marginTop: 18, padding: '10px 14px', background: 'var(--panel-2)', borderRadius: 8, fontSize: 11.5, color: 'var(--muted)', lineHeight: 1.5 }}>
        Hours substantiated by GPS-verified timecards and signed daily field reports. Backup detail available on request.
      </div>
    </div>
  );
}

Object.assign(window, { BillingView });
