// ---------- Bookkeeping (admin) ----------
// Two ledgers:
//   Top-ups  — every wallet credit with estimated cost & margin (GET /bookkeeping/topups)
//   Per call — every billed call, split into a Client cost and an Internal cost tab
//              (GET /bookkeeping/calls)

function bkMoney(n, dp = 2) {
  if (n == null || n === "") return "—";
  return `RM ${Number(n).toLocaleString("en-MY", { minimumFractionDigits: dp, maximumFractionDigits: dp })}`;
}

function bkUsd(n, dp = 4) {
  if (n == null || n === "") return "—";
  return `$${Number(n).toFixed(dp)}`;
}

function bkPct(n) {
  return n == null ? "—" : `${Number(n).toFixed(1)}%`;
}

function bkDate(iso) {
  if (!iso) return "—";
  return new Date(iso).toLocaleString("en-MY", { day: "numeric", month: "short", year: "numeric", hour: "numeric", minute: "2-digit" });
}

function bkDuration(sec) {
  const s = Math.round(Number(sec || 0));
  return `${Math.floor(s / 60)}:${String(s % 60).padStart(2, "0")}`;
}

function bkMarginTone(n) {
  if (n == null) return undefined;
  return n >= 0 ? "var(--ok)" : "var(--err, #dc2626)";
}

function bkDownloadCsv(filename, header, rows) {
  const esc = (v) => {
    const s = v == null ? "" : String(v);
    return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
  };
  const csv = [header, ...rows].map((r) => r.map(esc).join(",")).join("\n");
  const url = URL.createObjectURL(new Blob([csv], { type: "text/csv;charset=utf-8" }));
  const a = document.createElement("a");
  a.href = url;
  a.download = filename;
  a.click();
  window.setTimeout(() => URL.revokeObjectURL(url), 1000);
}

function BkStat({ label, value, sub, color }) {
  return (
    <div className="stat">
      <div className="stat-label">{label}</div>
      <div className="stat-value" style={color ? { color } : undefined}>{value}</div>
      {sub && <div className="muted text-11 mt-2">{sub}</div>}
    </div>
  );
}

// Drill-down for one call: every cost line, the vendor/model behind it, and
// what we charged vs what it cost us.
function BkCallDetail({ callId, onClose }) {
  const [detail, setDetail] = React.useState(null);
  const [err, setErr] = React.useState("");

  React.useEffect(() => {
    let cancelled = false;
    voxApi(`/bookkeeping/calls/${encodeURIComponent(callId)}`)
      .then((res) => { if (!cancelled) setDetail(res); })
      .catch((e) => { if (!cancelled) setErr(e.message); });
    return () => { cancelled = true; };
  }, [callId]);

  React.useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose]);

  const c = detail?.call;
  const s = detail?.stack;
  const fmtUsage = (x) => {
    if (x.usage == null) return "—";
    const n = Number(x.usage);
    return `${Number.isInteger(n) ? n.toLocaleString("en-MY") : n.toFixed(3)} ${x.unit || ""}`;
  };
  const fmtRate = (x) => {
    if (x.rate == null || x.rate === "") return "—";
    const n = Number(x.rate);
    return `RM ${n < 0.01 ? n.toFixed(6) : n.toFixed(4)}${x.rateUnit || ""}`;
  };
  const StackTile = ({ title, label, model, extra, recorded }) => (
    <div className="stat" style={{ padding: "10px 14px" }}>
      <div className="stat-label">{title}</div>
      <div className="text-13 strong mt-1">{label}</div>
      <div className="mono text-11 mt-1">{model || "—"}</div>
      {extra && <div className="muted text-11 mt-1">{extra}</div>}
      <div className="muted text-11 mt-1">{recorded ? "recorded on this call" : "from server config"}</div>
    </div>
  );

  return (
    <div className="modal-back" onClick={onClose}>
      <div className="modal" style={{ width: "min(980px, calc(100% - 32px))", maxHeight: "calc(100vh - 48px)", display: "flex", flexDirection: "column" }} onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <div>
            <div className="card-title">Call cost breakdown</div>
            {c && <div className="card-subtitle">{bkDate(c.date)} · {c.clientName || "—"} · {c.assistantName || "—"} · {bkDuration(c.durationSec)} · {c.endedReason || "—"}</div>}
          </div>
          <Btn variant="ghost" size="sm" icon="x" onClick={onClose} />
        </div>
        <div className="modal-body" style={{ overflowY: "auto" }}>
          {err && <div className="text-12" style={{ color: "var(--err)" }}>{err}</div>}
          {!detail && !err && <div className="muted text-12">Loading…</div>}
          {detail && (
            <>
              <div className="stat-grid mb-4" style={{ gridTemplateColumns: "repeat(auto-fit, minmax(150px, 1fr))" }}>
                <BkStat label="Billed to client" value={bkMoney(c.client.total, 4)} sub={c.pricingMode === "flat" ? `flat RM ${Number(c.ratePerMin).toFixed(4)}/min` : "auto-markup"} color="var(--ok)" />
                <BkStat label="Internal cost" value={bkMoney(c.internal.total, 4)} sub={`${bkUsd(c.internal.totalUsd)} USD`} />
                <BkStat label="Margin" value={bkMoney(c.marginMyr, 4)} sub={bkPct(c.marginPct)} color={bkMarginTone(c.marginMyr)} />
              </div>

              <div className="stat-grid mb-4" style={{ gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))" }}>
                <StackTile title="LLM" label={s.llm.label} model={s.llm.model} recorded={s.llm.recorded}
                  extra={`${Number(detail.tokens.input).toLocaleString("en-MY")} in / ${Number(detail.tokens.output).toLocaleString("en-MY")} out tokens · ${detail.turns} turns${s.llm.mixed ? ` · mixed: ${Object.entries(s.llm.mixed).map(([k, v]) => `${k}×${v}`).join(", ")}` : ""}`} />
                <StackTile title="ASR (speech-to-text)" label={s.asr.label} model={s.asr.model} recorded={s.asr.recorded} />
                <StackTile title="TTS (voice)" label={s.tts.label} model={s.tts.model} recorded={s.tts.recorded}
                  extra={s.tts.voice ? `voice: ${s.tts.voiceName}${s.tts.voiceName !== s.tts.voice ? ` (${s.tts.voice})` : ""}` : ""} />
              </div>

              <div style={{ overflowX: "auto" }}>
                <table className="tbl">
                  <thead>
                    <tr>
                      <th>Component</th><th>Vendor</th><th>Model / detail</th>
                      <th className="right">Usage</th><th className="right">Our rate</th>
                      <th className="right">Internal cost</th><th className="right">Share</th>
                    </tr>
                  </thead>
                  <tbody>
                    {detail.components.map((x) => (
                      <tr key={x.key}>
                        <td className="text-12 strong">{x.label}</td>
                        <td className="text-12">{x.vendor || "—"}</td>
                        <td className="mono text-11">{x.model || "—"}</td>
                        <td className="mono right text-12">{fmtUsage(x)}</td>
                        <td className="mono right text-11 muted">{fmtRate(x)}</td>
                        <td className="mono right text-12 strong">{bkMoney(x.internalCost, 4)}</td>
                        <td className="mono right text-11 muted">{c.internal.total > 0 ? `${((x.internalCost / c.internal.total) * 100).toFixed(0)}%` : "—"}</td>
                      </tr>
                    ))}
                    {detail.components.length === 0 && <tr><td colSpan={7} className="muted text-12">No cost breakdown recorded for this call.</td></tr>}
                  </tbody>
                  <tfoot>
                    <tr className="strong">
                      <td colSpan={5} className="text-12">Total internal cost</td>
                      <td className="mono right text-12">{bkMoney(c.internal.total, 4)}</td>
                      <td />
                    </tr>
                    <tr>
                      <td colSpan={5} className="text-12">Billed to client{c.pricingMode === "flat" ? ` (${(c.durationSec / 60).toFixed(2)} min × RM ${Number(c.ratePerMin).toFixed(4)}${c.client.events ? " + SMS/WhatsApp" : ""})` : ""}</td>
                      <td className="mono right text-12" style={{ color: "var(--ok)" }}>{bkMoney(c.client.total, 4)}</td>
                      <td />
                    </tr>
                    <tr className="strong">
                      <td colSpan={5} className="text-12">Margin</td>
                      <td className="mono right text-12" style={{ color: bkMarginTone(c.marginMyr) }}>{bkMoney(c.marginMyr, 4)}</td>
                      <td className="mono right text-11">{bkPct(c.marginPct)}</td>
                    </tr>
                  </tfoot>
                </table>
              </div>
              <div className="muted text-11 mt-3">
                TTS provider and voice, and the LLM provider of each turn, are recorded on the call. Model names marked "from server config" are what the server is set to use now. Call ID: <span className="mono">{c.id}</span>
              </div>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

function BookkeepingView({ clients = [] }) {
  const today = new Date().toISOString().slice(0, 10);
  const [tab, setTab] = React.useState("topups");
  const [callTab, setCallTab] = React.useState("client");
  const [clientId, setClientId] = React.useState("");
  const [from, setFrom] = React.useState("");
  const [to, setTo] = React.useState("");
  const [kind, setKind] = React.useState("");
  const [data, setData] = React.useState(null);
  const [loading, setLoading] = React.useState(false);
  const [err, setErr] = React.useState("");
  const [reloadKey, setReloadKey] = React.useState(0);
  const [showAdd, setShowAdd] = React.useState(false);
  const [form, setForm] = React.useState({ clientId: "", amount: "", date: today, note: "", kind: "paid" });
  const [saving, setSaving] = React.useState(false);
  const [openCallId, setOpenCallId] = React.useState(null);

  React.useEffect(() => {
    let cancelled = false;
    setLoading(true);
    setErr("");
    const params = new URLSearchParams();
    if (clientId) params.set("clientId", clientId);
    if (from) params.set("from", new Date(`${from}T00:00:00`).toISOString());
    if (to) params.set("to", new Date(`${to}T23:59:59`).toISOString());
    if (kind && tab === "topups") params.set("kind", kind);
    voxApi(`/bookkeeping/${tab === "topups" ? "topups" : "calls"}?${params.toString()}`)
      .then((res) => { if (!cancelled) setData(res); })
      .catch((e) => { if (!cancelled) { setErr(e.message); setData(null); } })
      .finally(() => { if (!cancelled) setLoading(false); });
    return () => { cancelled = true; };
  }, [tab, clientId, from, to, kind, reloadKey]);

  // Data from the other tab's endpoint must never render under this tab's columns.
  const rows = data && (tab === "topups" ? data.totals?.topups != null : data.totals?.calls != null) ? data.rows : null;
  const totals = rows ? data.totals : null;

  async function saveTopup() {
    const amount = Number(form.amount);
    if (!form.clientId || !(amount > 0)) { alert("Pick a client and enter an amount above 0."); return; }
    setSaving(true);
    try {
      await voxApi(`/wallet/${form.clientId}/topup`, {
        method: "POST",
        body: JSON.stringify({
          amountMyr: amount,
          note: form.note.trim(),
          occurredAt: form.date ? new Date(`${form.date}T12:00:00`).toISOString() : undefined,
          kind: form.kind,
        }),
      });
      setShowAdd(false);
      setForm({ clientId: "", amount: "", date: today, note: "", kind: "paid" });
      setReloadKey((k) => k + 1);
    } catch (e) {
      alert(`Could not save top-up: ${e.message}`);
    } finally {
      setSaving(false);
    }
  }

  async function reverseTopup(row) {
    const reason = window.prompt(
      `Reverse the ${bkMoney(row.amountMyr)} top-up for ${row.clientName || row.company} on ${bkDate(row.date)}?\n\n`
      + `This takes ${bkMoney(row.amountMyr)} back out of their wallet. The entry stays in the ledger, marked reversed.\n\nReason (required):`,
    );
    if (reason == null) return;
    if (!reason.trim()) { alert("A reason is required to reverse a top-up."); return; }
    try {
      await voxApi(`/wallet/topups/${encodeURIComponent(row.id)}/reverse`, {
        method: "POST",
        body: JSON.stringify({ reason: reason.trim() }),
      });
      setReloadKey((k) => k + 1);
    } catch (e) {
      alert(`Could not reverse top-up: ${e.message}`);
    }
  }

  function exportCsv() {
    if (!rows) return;
    const stamp = new Date().toISOString().slice(0, 10);
    if (tab === "topups") {
      bkDownloadCsv(`voxpro-topups-${stamp}.csv`,
        ["Date", "Client", "Company", "Type", "Amount (MYR)", "RM/min", "Cost ratio", "Est. cost (USD)", "Est. cost (MYR)", "Est. margin (MYR)", "Margin %", "Balance after", "Note", "Recorded by", "Reversed at", "Reversed by", "Reversal reason"],
        rows.map((x) => [x.date, x.clientName, x.company, x.kind || "paid", x.amountMyr, x.ratePerMin || "", x.costRatio ?? "", x.estCostUsd ?? "", x.estCostMyr ?? "", x.estMarginMyr ?? "", x.estMarginPct ?? "", x.balanceAfter, x.note, x.recordedBy, x.reversedAt || "", x.reversedBy, x.reversalReason]));
    } else if (callTab === "client") {
      bkDownloadCsv(`voxpro-calls-client-cost-${stamp}.csv`,
        ["Date", "Call ID", "Client", "Company", "Assistant", "Contact", "Outcome", "Duration (s)", "Pricing", "RM/min", "Voice (MYR)", "SMS/WhatsApp (MYR)", "Total billed (MYR)"],
        rows.map((x) => [x.date, x.id, x.clientName, x.company, x.assistantName, x.contact, x.endedReason, x.durationSec, x.pricingMode, x.ratePerMin || "", x.client.voice, x.client.events, x.client.total]));
    } else {
      bkDownloadCsv(`voxpro-calls-internal-cost-${stamp}.csv`,
        ["Date", "Call ID", "Client", "Assistant", "Duration (s)", "ASR (MYR)", "LLM (MYR)", "TTS (MYR)", "Platform (MYR)", "Server (MYR)", "SIP trunk (MYR)", "SMS/WhatsApp (MYR)", "Internal total (MYR)", "Internal total (USD)", "Billed (MYR)", "Margin (MYR)", "Margin %"],
        rows.map((x) => [x.date, x.id, x.clientName, x.assistantName, x.durationSec, x.internal.stt, x.internal.llm, x.internal.tts, x.internal.platform, x.internal.server, x.internal.telephony || 0, x.internal.events, x.internal.total, x.internal.totalUsd, x.client.total, x.marginMyr, x.marginPct ?? ""]));
    }
  }

  const sortedClients = React.useMemo(
    () => [...clients].sort((a, b) => String(a.company || a.name).localeCompare(String(b.company || b.name))),
    [clients],
  );

  return (
    <div>
      <div className="ph">
        <div>
          <h1 className="ph-title">Bookkeeping</h1>
          <div className="ph-subtitle">
            {tab === "topups"
              ? "Full top-up ledger — every client credit with cost & margin breakdown"
              : "Per-call ledger — what each call billed the client vs what it cost us"}
          </div>
        </div>
        <div className="ph-actions">
          <Btn variant="ghost" icon="refresh" size="sm" onClick={() => setReloadKey((k) => k + 1)} disabled={loading}>Refresh</Btn>
          {tab === "topups" && <Btn variant="ghost" icon="plus" size="sm" onClick={() => setShowAdd((v) => !v)}>Add Backlog Entry</Btn>}
          <Btn variant="primary" icon="download" size="sm" onClick={exportCsv} disabled={!rows || rows.length === 0}>Download CSV</Btn>
        </div>
      </div>

      <Tabs
        tabs={[{ id: "topups", label: "Top-ups" }, { id: "calls", label: "Per call" }]}
        active={tab}
        onSelect={setTab}
      />

      {showAdd && tab === "topups" && (
        <Card title="Add backlog top-up" subtitle="Credits the client's wallet and records it in the ledger, dated to when the payment happened" style={{ marginBottom: 16 }}>
          <div className="row gap-3" style={{ flexWrap: "wrap", alignItems: "flex-end" }}>
            <Field label="Client">
              <Select value={form.clientId} onChange={(e) => setForm({ ...form, clientId: e.target.value })}>
                <option value="">Select client…</option>
                {sortedClients.map((c) => <option key={c.id} value={c.id}>{c.company || c.name}</option>)}
              </Select>
            </Field>
            <Field label="Type">
              <Select value={form.kind} onChange={(e) => setForm({ ...form, kind: e.target.value })}>
                <option value="paid">Paid by client</option>
                <option value="free">Free credit</option>
                <option value="adjustment">Adjustment</option>
              </Select>
            </Field>
            <Field label="Amount (RM)"><Input type="number" min="0" step="0.01" value={form.amount} onChange={(e) => setForm({ ...form, amount: e.target.value })} /></Field>
            <Field label="Payment date"><Input type="date" value={form.date} onChange={(e) => setForm({ ...form, date: e.target.value })} /></Field>
            <Field label="Note"><Input value={form.note} placeholder="e.g. Invoice #123, bank transfer" onChange={(e) => setForm({ ...form, note: e.target.value })} /></Field>
            <Btn variant="primary" size="sm" onClick={saveTopup} disabled={saving}>{saving ? "Saving…" : "Save top-up"}</Btn>
            <Btn variant="ghost" size="sm" onClick={() => setShowAdd(false)}>Cancel</Btn>
          </div>
        </Card>
      )}

      {totals && tab === "topups" && (
        <div className="stat-grid mb-4" style={{ gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))" }}>
          <BkStat label="Total invoiced" value={bkMoney(totals.invoicedMyr)} sub={`${totals.paidTopups ?? totals.topups} paid top-ups`} color="var(--ok)" />
          <BkStat label="Free credit given" value={bkMoney(totals.freeCreditMyr || 0)} sub="free credit + adjustments, not revenue" />
          <BkStat label="Est. internal cost" value={bkMoney(totals.estCostMyr)} sub={`${bkUsd(totals.estCostUsd, 2)} USD`} />
          <BkStat label="Est. margin" value={bkMoney(totals.estMarginMyr)} color={bkMarginTone(totals.estMarginMyr)} />
          <BkStat label="Avg margin %" value={bkPct(totals.estMarginPct)} sub="across all top-ups" color={bkMarginTone(totals.estMarginPct)} />
          <BkStat label="Wallet balance now" value={bkMoney(totals.balanceMyr)} sub={clientId ? "this client" : "all clients"} />
        </div>
      )}

      {totals && tab === "calls" && (
        <div className="stat-grid mb-4" style={{ gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))" }}>
          <BkStat label="Billed to clients" value={bkMoney(totals.billedMyr)} sub={`${totals.calls} calls · ${totals.minutes} min`} color="var(--ok)" />
          <BkStat label="Internal cost" value={bkMoney(totals.internalMyr)} sub={`${bkUsd(totals.internalUsd, 2)} USD`} />
          <BkStat label="Margin" value={bkMoney(totals.marginMyr)} color={bkMarginTone(totals.marginMyr)} />
          <BkStat label="Margin %" value={bkPct(totals.marginPct)} sub="across all calls" color={bkMarginTone(totals.marginPct)} />
        </div>
      )}

      <Card style={{ marginBottom: 16 }}>
        <div className="row gap-3" style={{ flexWrap: "wrap", alignItems: "flex-end" }}>
          <Field label="Client">
            <Select value={clientId} onChange={(e) => setClientId(e.target.value)}>
              <option value="">All clients</option>
              {sortedClients.map((c) => <option key={c.id} value={c.id}>{c.company || c.name}</option>)}
            </Select>
          </Field>
          {tab === "topups" && (
            <Field label="Type">
              <Select value={kind} onChange={(e) => setKind(e.target.value)}>
                <option value="">All types</option>
                <option value="paid">Paid by client</option>
                <option value="free">Free credit</option>
                <option value="adjustment">Adjustments</option>
              </Select>
            </Field>
          )}
          <Field label="From"><Input type="date" value={from} onChange={(e) => setFrom(e.target.value)} /></Field>
          <Field label="To"><Input type="date" value={to} onChange={(e) => setTo(e.target.value)} /></Field>
          {(clientId || from || to || kind) && <Btn variant="ghost" size="sm" onClick={() => { setClientId(""); setFrom(""); setTo(""); setKind(""); }}>Clear</Btn>}
          <div className="muted text-12" style={{ marginLeft: "auto" }}>{loading ? "Loading…" : rows ? `${rows.length} records` : ""}</div>
        </div>
      </Card>

      {err && <div className="text-12 mb-3" style={{ color: "var(--err)" }}>{err}</div>}

      {rows && tab === "topups" && (
        <Card pad="none">
          <div style={{ overflowX: "auto" }}>
            <table className="tbl">
              <thead>
                <tr>
                  <th>Date &amp; time</th><th>Client</th><th>Company</th>
                  <th className="right">Invoiced (MYR)</th><th className="right">RM/min</th>
                  <th className="right">Est. cost (USD)</th><th className="right">Est. cost (MYR)</th>
                  <th className="right">Est. margin (MYR)</th><th className="right">Margin %</th>
                  <th className="right">Balance after</th><th>Note</th><th>Recorded by</th><th className="right">Actions</th>
                </tr>
              </thead>
              <tbody>
                {rows.map((x) => (
                  <tr key={x.id} style={x.reversedAt ? { opacity: 0.55, textDecoration: "line-through" } : undefined}>
                    <td className="muted text-12">{bkDate(x.date)}</td>
                    <td className="text-12 strong">{x.clientName || "—"}</td>
                    <td className="text-12">{x.company || "—"}</td>
                    {x.kind === "paid" ? (
                      <td className="mono right text-12 strong" style={{ color: "var(--ok)" }}>{bkMoney(x.amountMyr)}</td>
                    ) : (
                      <td className="mono right text-12" title="Not revenue — wallet credit only">
                        <Badge tone="neutral">{x.kind === "free" ? "Free credit" : "Adjustment"}</Badge> {bkMoney(x.amountMyr)}
                      </td>
                    )}
                    <td className="mono right text-12 muted">{x.ratePerMin ? Number(x.ratePerMin).toFixed(4) : "markup"}</td>
                    <td className="mono right text-12">{bkUsd(x.estCostUsd)}</td>
                    <td className="mono right text-12">{bkMoney(x.estCostMyr)}</td>
                    {x.kind === "paid" ? (
                      <>
                        <td className="mono right text-12 strong" style={{ color: bkMarginTone(x.estMarginMyr) }}>{bkMoney(x.estMarginMyr)}</td>
                        <td className="right text-12">{x.estMarginPct == null ? <span className="muted" title="No billed usage yet for this client, so no cost ratio">—</span> : <Badge tone={x.estMarginPct >= 0 ? "ok" : "err"}>{bkPct(x.estMarginPct)}</Badge>}</td>
                      </>
                    ) : (
                      <>
                        <td className="mono right text-12 muted" title="Free credit earns nothing; usage it funds costs us the est. cost">—</td>
                        <td className="right text-12 muted">—</td>
                      </>
                    )}
                    <td className="mono right text-12">{bkMoney(x.balanceAfter)}</td>
                    <td className="muted text-12">{x.note || "—"}</td>
                    <td className="muted text-12">{x.recordedBy || "—"}</td>
                    <td className="right text-12" style={{ textDecoration: "none" }}>
                      {x.reversedAt
                        ? <span title={`Reversed ${bkDate(x.reversedAt)} by ${x.reversedBy || "admin"}: ${x.reversalReason}`}><Badge tone="err">Reversed</Badge></span>
                        : <Btn variant="ghost" size="sm" icon="trash" title="Reverse this top-up" onClick={() => reverseTopup(x)} style={{ color: "var(--err, #dc2626)" }} />}
                    </td>
                  </tr>
                ))}
                {rows.length === 0 && <tr><td colSpan={13} className="muted text-12">No top-ups in this range.</td></tr>}
              </tbody>
              {rows.length > 0 && (
                <tfoot>
                  <tr className="strong">
                    <td colSpan={3} className="text-12">TOTALS ({totals.topups} top-ups{totals.reversed ? `, ${totals.reversed} reversed excluded` : ""})</td>
                    <td className="mono right text-12" style={{ color: "var(--ok)" }}>{bkMoney(totals.invoicedMyr)}</td>
                    <td />
                    <td className="mono right text-12">{bkUsd(totals.estCostUsd, 2)}</td>
                    <td className="mono right text-12">{bkMoney(totals.estCostMyr)}</td>
                    <td className="mono right text-12" style={{ color: bkMarginTone(totals.estMarginMyr) }}>{bkMoney(totals.estMarginMyr)}</td>
                    <td className="right text-12">{bkPct(totals.estMarginPct)}</td>
                    <td colSpan={4} />
                  </tr>
                </tfoot>
              )}
            </table>
          </div>
          <div className="muted text-11" style={{ padding: "10px 16px" }}>
            Est. cost = top-up amount × that client's all-time internal cost ÷ billed amount on real calls, SMS &amp; WhatsApp. USD at RM {data.usdToMyr}/USD.
          </div>
        </Card>
      )}

      {rows && tab === "calls" && (
        <Card pad="none">
          <div style={{ padding: "0 16px" }}>
            <Tabs
              tabs={[{ id: "client", label: "Client cost" }, { id: "internal", label: "Internal cost" }]}
              active={callTab}
              onSelect={setCallTab}
            />
          </div>
          <div style={{ overflowX: "auto" }}>
            {callTab === "client" ? (
              <table className="tbl">
                <thead>
                  <tr>
                    <th>Date &amp; time</th><th>Client</th><th>Assistant</th><th>Contact</th><th>Outcome</th>
                    <th className="right">Duration</th><th>Pricing</th>
                    <th className="right">Voice (MYR)</th><th className="right">SMS/WA (MYR)</th><th className="right">Total billed</th>
                    <th className="right">Internal cost</th><th className="right">Margin</th>
                  </tr>
                </thead>
                <tbody>
                  {rows.map((x) => (
                    <tr key={x.id} onClick={() => setOpenCallId(x.id)} style={{ cursor: "pointer" }} title="Click for cost breakdown">
                      <td className="muted text-12">{bkDate(x.date)}</td>
                      <td className="text-12 strong">{x.clientName || "—"}</td>
                      <td className="text-12">{x.assistantName || "—"}</td>
                      <td className="text-12">{x.contact || "—"}</td>
                      <td className="muted text-12">{x.endedReason || "—"}</td>
                      <td className="mono right text-12">{bkDuration(x.durationSec)}</td>
                      <td className="text-12">{x.pricingMode === "flat" ? <Badge tone="neutral">RM {Number(x.ratePerMin).toFixed(4)}/min</Badge> : <Badge tone="neutral">markup</Badge>}</td>
                      <td className="mono right text-12">{bkMoney(x.client.voice, 4)}</td>
                      <td className="mono right text-12">{x.client.events ? bkMoney(x.client.events, 4) : "—"}</td>
                      <td className="mono right text-12 strong" style={{ color: "var(--ok)" }}>{bkMoney(x.client.total, 4)}</td>
                      <td className="mono right text-12">{bkMoney(x.internal.total, 4)}</td>
                      <td className="mono right text-12 strong" style={{ color: bkMarginTone(x.marginMyr) }}>{bkMoney(x.marginMyr, 4)}</td>
                    </tr>
                  ))}
                  {rows.length === 0 && <tr><td colSpan={12} className="muted text-12">No calls in this range.</td></tr>}
                </tbody>
                {rows.length > 0 && (
                  <tfoot>
                    <tr className="strong">
                      <td colSpan={5} className="text-12">TOTALS ({rows.length} calls)</td>
                      <td className="mono right text-12">{totals.minutes} min</td>
                      <td />
                      <td className="mono right text-12">{bkMoney(rows.reduce((s, x) => s + x.client.voice, 0))}</td>
                      <td className="mono right text-12">{bkMoney(rows.reduce((s, x) => s + x.client.events, 0))}</td>
                      <td className="mono right text-12" style={{ color: "var(--ok)" }}>{bkMoney(totals.billedMyr)}</td>
                      <td className="mono right text-12">{bkMoney(totals.internalMyr)}</td>
                      <td className="mono right text-12" style={{ color: bkMarginTone(totals.marginMyr) }}>{bkMoney(totals.marginMyr)}</td>
                    </tr>
                  </tfoot>
                )}
              </table>
            ) : (
              <table className="tbl">
                <thead>
                  <tr>
                    <th>Date &amp; time</th><th>Client</th><th>Assistant</th><th className="right">Duration</th>
                    <th className="right">ASR</th><th className="right">LLM</th><th className="right">TTS</th>
                    <th className="right">Platform</th><th className="right">Server</th><th className="right">SIP</th><th className="right">SMS/WA</th>
                    <th className="right">Internal (MYR)</th><th className="right">Internal (USD)</th>
                    <th className="right">Billed</th><th className="right">Margin</th><th className="right">Margin %</th>
                  </tr>
                </thead>
                <tbody>
                  {rows.map((x) => (
                    <tr key={x.id} onClick={() => setOpenCallId(x.id)} style={{ cursor: "pointer" }} title="Click for cost breakdown">
                      <td className="muted text-12">{bkDate(x.date)}</td>
                      <td className="text-12 strong">{x.clientName || "—"}</td>
                      <td className="text-12">{x.assistantName || "—"}</td>
                      <td className="mono right text-12">{bkDuration(x.durationSec)}</td>
                      <td className="mono right text-12">{Number(x.internal.stt).toFixed(4)}</td>
                      <td className="mono right text-12">{Number(x.internal.llm).toFixed(4)}</td>
                      <td className="mono right text-12">{Number(x.internal.tts).toFixed(4)}</td>
                      <td className="mono right text-12">{Number(x.internal.platform).toFixed(4)}</td>
                      <td className="mono right text-12">{Number(x.internal.server).toFixed(4)}</td>
                      <td className="mono right text-12">{Number(x.internal.telephony || 0).toFixed(4)}</td>
                      <td className="mono right text-12">{x.internal.events ? Number(x.internal.events).toFixed(4) : "—"}</td>
                      <td className="mono right text-12 strong">{bkMoney(x.internal.total, 4)}</td>
                      <td className="mono right text-12">{bkUsd(x.internal.totalUsd)}</td>
                      <td className="mono right text-12">{bkMoney(x.client.total, 4)}</td>
                      <td className="mono right text-12 strong" style={{ color: bkMarginTone(x.marginMyr) }}>{bkMoney(x.marginMyr, 4)}</td>
                      <td className="right text-12">{x.marginPct == null ? "—" : <Badge tone={x.marginPct >= 0 ? "ok" : "err"}>{bkPct(x.marginPct)}</Badge>}</td>
                    </tr>
                  ))}
                  {rows.length === 0 && <tr><td colSpan={16} className="muted text-12">No calls in this range.</td></tr>}
                </tbody>
                {rows.length > 0 && (
                  <tfoot>
                    <tr className="strong">
                      <td colSpan={3} className="text-12">TOTALS ({rows.length} calls)</td>
                      <td className="mono right text-12">{totals.minutes} min</td>
                      {["stt", "llm", "tts", "platform", "server", "telephony", "events"].map((k) => (
                        <td key={k} className="mono right text-12">{rows.reduce((s, x) => s + Number(x.internal[k] || 0), 0).toFixed(2)}</td>
                      ))}
                      <td className="mono right text-12">{bkMoney(totals.internalMyr)}</td>
                      <td className="mono right text-12">{bkUsd(totals.internalUsd, 2)}</td>
                      <td className="mono right text-12">{bkMoney(totals.billedMyr)}</td>
                      <td className="mono right text-12" style={{ color: bkMarginTone(totals.marginMyr) }}>{bkMoney(totals.marginMyr)}</td>
                      <td className="right text-12">{bkPct(totals.marginPct)}</td>
                    </tr>
                  </tfoot>
                )}
              </table>
            )}
          </div>
          <div className="muted text-11" style={{ padding: "10px 16px" }}>
            Click any call to see each component we pay for (LLM, ASR, TTS, platform, server, SMS/WhatsApp) and the vendor/model behind it.
            Internal costs use the same per-call cost model as the call log's Cost breakdown tab. USD at RM {data.usdToMyr}/USD. Voicemail calls bill RM 0.
          </div>
        </Card>
      )}

      {openCallId && <BkCallDetail callId={openCallId} onClose={() => setOpenCallId(null)} />}
    </div>
  );
}

Object.assign(window, { BookkeepingView });
