// Bylt Capital CRM — commissions: who is credited on a funded deal, what the
// lender owes the office, and what the office owes each person.
//
// Owners, Admins and Partners see and change everything (an Admin never sees
// the Owner's private deals); a Bookkeeper sees everything and changes nothing.
// Everyone else sees only their own lines: the server never sends them anyone
// else's payout, an override on their deals, or the office's share, so there is
// nothing here to hide client-side.
//
// Clawbacks (Round 14): a lender taking back all or part of a deal's
// commission. Each person's part comes off a payout not yet made, or is owed
// back to the office until it is marked paid back.

// Sheets opened from inside the deal file are drawn at the top of the page, so
// they cover the whole window rather than just the file's column.
const todayLocal = () => fmt.localDay(new Date().toISOString());
const pctText = (n) => `${Math.round(fmt.num(n) * 100) / 100}%`;
const lineWhat = (l) => (l.kind === "override" ? `Override on ${l.onName || "a rep"}` : "Commission");
const lineTerms = (l) => (l.kind === "override" ? `${pctText(l.pct)} of the commission${l.sharePct < 100 ? ` on their ${pctText(l.sharePct)} share` : ""}` : `${l.sharePct < 100 ? pctText(l.sharePct) + " of the deal · " : ""}${pctText(l.pct)} payout`);

const REASONS = [{ id: "default", label: "Merchant defaulted" }, { id: "payoff", label: "Paid off early" }, { id: "other", label: "Other" }];
const reasonLabel = (id) => (REASONS.find(r => r.id === id) || REASONS[2]).label;
const cents = (x) => Math.round(x * 100) / 100;

// Where one payout stands, in words.
function payoutStatus(rec, line) {
  if (line.paidAt) return { tone: "funded", label: `Paid ${fmt.day(line.paidAt)}` };
  if (fmt.num(line.amount) > 0 && fmt.num(line.net) <= 0 && fmt.num(line.clawed) > 0) return { tone: "declined", label: "Clawed back" };
  if (!(fmt.num(rec.amount) > 0)) return { tone: "none", label: "Commission not entered", plain: true };
  if (rec.lender.status === "owed") return { tone: "new", label: "Waiting on lender" };
  return { tone: "submitted", label: "Ready to pay" };
}
const lenderStatus = (rec) => (rec.inHouse ? { tone: "none", label: "Funded in-house", plain: true }
  : rec.lender.status === "received" ? { tone: "funded", label: `Received ${fmt.day(rec.lender.receivedAt)}` }
  : fmt.num(rec.amount) > 0 ? { tone: "submitted", label: "Owed by lender" } : { tone: "none", label: "Not entered", plain: true });

// ── Forms ───────────────────────────────────────────────────────────────────
function ReceivedSheet({ rec, onClose, onSaved }) {
  const noteKnown = !!rec.lender && rec.lender.note !== undefined;       // opened from a list, the saved note isn't loaded
  const [v, set] = useForm({ date: todayLocal(), amount: String(rec.amount || ""), note: (noteKnown && rec.lender.note) || "" });
  const save = useSave(onSaved);
  const submit = () => {
    if (!/^\d{4}-\d{2}-\d{2}$/.test(v.date)) return save.setError("Pick the date it was received.");
    const amt = fmt.parseMoney(v.amount);
    if (amt === "" || Number.isNaN(amt) || amt <= 0) return save.setError("Enter the amount received.");
    const lender = { status: "received", receivedAt: v.date, receivedAmount: amt };
    if (noteKnown || v.note.trim()) lender.note = v.note;                  // a blank box never wipes a note it couldn't show
    save.run(() => API.saveDealCommission(rec.dealId, { lender }));
  };
  return (
    <Sheet eyebrow={rec.biz} title="Commission received" onClose={onClose} onSubmit={submit} submitLabel="Mark received" busy={save.busy} error={save.error}>
      <div className="form-section">
        <p className="dim" style={{ marginBottom: 12 }}>{rec.payer || "The lender"} owes {fmt.money(rec.amount)} on this deal.</p>
        <div className="form-grid">
          <Field label="Date received"><TextInput value={v.date} onChange={x => set("date", x)} type="date" /></Field>
          <Field label="Amount received" hint="Change it if the lender paid a different amount."><TextInput value={v.amount} onChange={x => set("amount", x)} inputMode="decimal" /></Field>
          <Field label="Note" full hint="Only Admins see this."><TextInput value={v.note} onChange={x => set("note", x)} placeholder="Wire or ACH reference…" /></Field>
        </div>
      </div>
    </Sheet>
  );
}

function PaySheet({ items, onClose, onSaved }) {
  const [v, set] = useForm({ date: todayLocal(), note: "" });
  const save = useSave(onSaved);
  const total = items.reduce((t, i) => t + fmt.num(i.amount), 0);
  const names = [...new Set(items.map(i => i.name))];
  const waiting = items.filter(i => i.lenderStatus === "owed").length;
  const submit = () => {
    if (!/^\d{4}-\d{2}-\d{2}$/.test(v.date)) return save.setError("Pick the date it was paid.");
    save.run(() => API.payCommissions(items.map(i => ({ dealId: i.dealId, lineId: i.lineId })), { date: v.date, note: v.note }));
  };
  return (
    <Sheet eyebrow="Commissions" title={names.length === 1 ? `Pay ${names[0]}` : "Mark payouts paid"} onClose={onClose} onSubmit={submit}
           submitLabel={`Mark ${fmt.money(total)} paid`} busy={save.busy} error={save.error}>
      <div className="form-section">
        {waiting ? <div className="banner info" style={{ marginBottom: 12 }}>{waiting === items.length ? "The lender hasn't" : `On ${waiting} of these the lender hasn't`} paid the office yet. You can still pay now.</div> : null}
        <div className="card card-flush" style={{ marginBottom: 14 }}>
          {items.map(i => (
            <div className="row" key={i.dealId + i.lineId}>
              <div className="grow"><div className="title">{i.biz}</div><div className="line">{names.length > 1 ? i.name + " · " : ""}{lineWhat(i)}</div></div>
              <div className="right"><b className="tnum">{fmt.money(i.amount)}</b></div>
            </div>
          ))}
        </div>
        <div className="form-grid">
          <Field label="Date paid"><TextInput value={v.date} onChange={x => set("date", x)} type="date" /></Field>
          <Field label="Note" hint="The person being paid can see this."><TextInput value={v.note} onChange={x => set("note", x)} placeholder="Check number, Zelle, payroll…" /></Field>
        </div>
      </div>
    </Sheet>
  );
}

// A lender took back all or part of the commission on a deal.
function ClawbackSheet({ rec, onClose, onSaved }) {
  const left = cents(fmt.num(rec.amount) - fmt.num(rec.clawed));
  const [v, set] = useForm({ date: todayLocal(), all: true, amount: "", reason: "default", note: "" });
  const save = useSave(onSaved);
  const amt = v.all ? left : fmt.parseMoney(v.amount);
  const ok = amt !== "" && !Number.isNaN(amt) && amt > 0 && amt <= left + 0.005;
  // The same split the server makes: each person's share of the commission.
  const parts = rec.lines.filter(l => fmt.num(l.amount) > 0).map(l => ({ l, part: ok ? Math.min(fmt.num(l.net), cents(amt * fmt.num(l.amount) / fmt.num(rec.amount))) : 0 }));
  const office = ok ? cents(amt - parts.reduce((t, x) => t + x.part, 0)) : 0;
  const submit = () => {
    if (!/^\d{4}-\d{2}-\d{2}$/.test(v.date)) return save.setError("Pick the date the lender took it back.");
    if (!ok) return save.setError(`Enter an amount above $0 and no more than ${fmt.money(left)}.`);
    save.run(() => API.addClawback(rec.dealId, v.all ? { all: true, at: v.date, reason: v.reason, note: v.note } : { amount: amt, at: v.date, reason: v.reason, note: v.note }));
  };
  return (
    <Sheet eyebrow={rec.biz} title="Record a clawback" onClose={onClose} onSubmit={submit} submitLabel={ok ? `Record ${fmt.money(amt)} clawback` : "Record clawback"} busy={save.busy} error={save.error}>
      <div className="form-section">
        <p className="dim" style={{ marginBottom: 12 }}>{rec.payer || "The lender"} is taking back commission on this deal. It is split over everyone paid on it by what each earned; the office absorbs the rest.</p>
        <div className="form-grid">
          <Field label="Date taken back"><TextInput value={v.date} onChange={x => set("date", x)} type="date" /></Field>
          <Field label="Why"><Select value={v.reason} onChange={x => set("reason", x)} options={REASONS.map(r => ({ value: r.id, label: r.label }))} /></Field>
          <label className="check full"><input type="checkbox" checked={v.all} onChange={e => set("all", e.target.checked)} /> All of it ({fmt.money(left)}{fmt.num(rec.clawed) > 0 ? " left after earlier clawbacks" : ""})</label>
          {!v.all ? <Field label="Amount taken back" full><TextInput value={v.amount} onChange={x => set("amount", x)} inputMode="decimal" placeholder="$" /></Field> : null}
          <Field label="Note" full hint="Only people who see the office's commissions see this."><TextInput value={v.note} onChange={x => set("note", x)} placeholder="Defaulted after 14 payments…" /></Field>
        </div>
      </div>
      {ok ? (
        <div className="form-section">
          <span className="label">How it splits</span>
          <div className="card card-flush" style={{ marginTop: 8 }}>
            {parts.map(({ l, part }) => (
              <div className="row" key={l.id}>
                <div className="grow"><div className="title">{l.name}{l.kind === "override" ? " (override)" : ""}</div><div className="line">{l.paidAt ? `Already paid ${fmt.money(l.paidAmount)}: owes ${fmt.money(part)} back` : `Not paid yet: the payout drops to ${fmt.money(cents(fmt.num(l.net) - part))}`}</div></div>
                <div className="right"><b className="tnum">{fmt.money(part)}</b></div>
              </div>
            ))}
            <div className="row"><div className="grow"><div className="title">Office</div><div className="line">Its own share of the commission</div></div><div className="right"><b className="tnum">{fmt.money(office)}</b></div></div>
          </div>
        </div>
      ) : null}
    </Sheet>
  );
}

// Someone paid back their part of a clawback.
function RecoverSheet({ items, onClose, onSaved }) {
  const one = items.length === 1;
  const total = items.reduce((t, i) => t + fmt.num(i.owed), 0);
  const [v, set] = useForm({ date: todayLocal(), amount: String(cents(total)), note: "" });
  const save = useSave(onSaved);
  const names = [...new Set(items.map(i => i.name))];
  const submit = () => {
    if (!/^\d{4}-\d{2}-\d{2}$/.test(v.date)) return save.setError("Pick the date it was paid back.");
    const amt = fmt.parseMoney(v.amount);
    if (one && (amt === "" || Number.isNaN(amt) || amt <= 0)) return save.setError("Enter the amount paid back.");
    const opts = { date: v.date, note: v.note };
    if (one) opts.amount = cents(amt + fmt.num(items[0].recovered));      // the total paid back on it so far
    save.run(() => API.recoverClawbacks(items.map(i => ({ dealId: i.dealId, clawbackId: i.clawbackId, lineId: i.lineId })), opts));
  };
  return (
    <Sheet eyebrow="Clawbacks" title={names.length === 1 ? `${names[0]} paid back` : "Mark clawbacks paid back"} onClose={onClose} onSubmit={submit} submitLabel="Mark paid back" busy={save.busy} error={save.error}>
      <div className="form-section">
        <div className="card card-flush" style={{ marginBottom: 14 }}>
          {items.map(i => (
            <div className="row" key={i.dealId + i.clawbackId + i.lineId}>
              <div className="grow"><div className="title">{i.biz}</div><div className="line">{names.length > 1 ? i.name + " · " : ""}clawed back {fmt.day(i.at)}{fmt.num(i.recovered) > 0 ? ` · ${fmt.money(i.recovered)} paid back already` : ""}</div></div>
              <div className="right"><b className="tnum">{fmt.money(i.owed)}</b></div>
            </div>
          ))}
        </div>
        <div className="form-grid">
          <Field label="Date paid back"><TextInput value={v.date} onChange={x => set("date", x)} type="date" /></Field>
          {one ? <Field label="Amount paid back" hint="Less than they owe if they paid part of it."><TextInput value={v.amount} onChange={x => set("amount", x)} inputMode="decimal" /></Field> : null}
          <Field label="Note" full><TextInput value={v.note} onChange={x => set("note", x)} placeholder="Check, Zelle, taken from a payout…" /></Field>
        </div>
      </div>
    </Sheet>
  );
}

// Admin: the commission on one deal — the amount, who is credited, and overrides.
function CommissionSheet({ rec, onClose, onSaved }) {
  const [users, setUsers] = useState(null);
  const [mode, setMode] = useState(rec.points != null ? "points" : "amount");
  const startAmount = rec.points != null ? String(rec.points) : rec.amount ? String(rec.amount) : "";
  const [amount, setAmount] = useState(startAmount);
  const paid = (id) => rec.lines.some(l => l.id === id && l.paidAt);
  const [reps, setReps] = useState(rec.lines.filter(l => l.kind === "rep").map(l => ({ userId: l.userId, sharePct: String(l.sharePct), pct: String(l.pct), locked: !!l.paidAt })));
  const [overs, setOvers] = useState(rec.lines.filter(l => l.kind === "override").map(l => ({ userId: l.userId, onUserId: l.onUserId, pct: String(l.pct), locked: !!l.paidAt })));
  const save = useSave(onSaved);
  const anyPaid = rec.lines.some(l => l.paidAt);
  useEffect(() => { API.users().then(setUsers).catch(() => setUsers([])); }, []);

  // The team, plus anyone already on this deal who has since been removed from it.
  const former = rec.lines.filter(l => !(users || []).some(u => u.id === l.userId)).map(l => ({ id: l.userId, name: l.name, active: false }));
  const people = (users || []).concat(former.filter((f, i) => former.findIndex(x => x.id === f.id) === i)).filter(u => u.active !== false || reps.some(r => r.userId === u.id) || overs.some(o => o.userId === u.id));
  const nameOf = (id) => ((users || []).find(u => u.id === id) || rec.lines.find(l => l.userId === id) || {}).name || "Team member";
  const options = (current, taken) => [{ value: "", label: "Choose…" }].concat(people.filter(u => u.id === current || !taken.includes(u.id)).map(u => ({ value: u.id, label: u.name })));
  const n = (s) => { const x = fmt.parseMoney(String(s).replace(/%/g, "")); return x === "" || Number.isNaN(x) ? 0 : x; };
  const badRate = (s) => { const x = fmt.parseMoney(String(s).replace(/%/g, "")); return x === "" || Number.isNaN(x) || x < 0 || x > 100; };
  const cents = (x) => Math.round(x * 100) / 100;
  const total = mode === "points" ? Math.round(fmt.num(rec.fundedAmount) * n(amount)) / 100 : n(amount);
  const shareOf = (id) => (reps.length === 1 ? 100 : n((reps.find(r => r.userId === id) || {}).sharePct));
  const repAmount = (r) => cents(total * shareOf(r.userId) * n(r.pct) / 10000);
  const overAmount = (o) => cents(total * shareOf(o.onUserId) * n(o.pct) / 10000);
  const office = Math.round((total - reps.reduce((t, r) => t + repAmount(r), 0) - overs.reduce((t, o) => t + overAmount(o), 0)) * 100) / 100;

  const setRep = (i, k, val) => setReps(list => list.map((r, j) => (j === i ? { ...r, [k]: val } : r)));
  const setOver = (i, k, val) => setOvers(list => list.map((o, j) => (j === i ? { ...o, [k]: val } : o)));
  // Picking a rep fills in their payout rate, and the overrides on file for them.
  const pickRep = (i, userId) => {
    const u = (users || []).find(x => x.id === userId), c = (u && u.commission) || {};
    const was = reps[i].userId;
    setReps(list => list.map((r, j) => (j === i ? { ...r, userId, pct: c.payoutPct != null ? String(c.payoutPct) : r.pct } : r)));
    setOvers(list => list.filter(o => o.onUserId !== was || o.locked).concat((c.overrides || []).filter(o => (users || []).some(x => x.id === o.userId)).map(o => ({ userId: o.userId, onUserId: userId, pct: String(o.pct) }))));
  };
  const addRep = () => setReps(list => (list.length === 1 ? [{ ...list[0], sharePct: "50" }] : list).concat([{ userId: "", sharePct: list.length === 1 ? "50" : "", pct: "" }]));
  const removeRep = (i) => { const gone = reps[i].userId; setReps(list => { const next = list.filter((_, j) => j !== i); return next.length === 1 ? [{ ...next[0], sharePct: "100" }] : next; }); setOvers(list => list.filter(o => o.onUserId !== gone)); };

  const submit = () => {
    if (reps.some(r => !r.userId)) return save.setError("Choose a team member on every line, or remove the empty one.");
    if (overs.some(o => !o.userId || !o.onUserId)) return save.setError("Each override needs who earns it and whose deal it is on.");
    if (reps.some(r => badRate(r.pct)) || overs.some(o => badRate(o.pct))) return save.setError("Each payout and override needs a percentage from 0 to 100.");
    if (reps.length > 1 && reps.some(r => badRate(r.sharePct) || n(r.sharePct) === 0)) return save.setError("Each rep needs a share of the deal above 0%.");
    if (reps.length > 1 && Math.abs(reps.reduce((t, r) => t + n(r.sharePct), 0) - 100) > 0.01) return save.setError("The reps' shares of the deal need to add up to 100%.");
    if (String(amount).trim() !== "" && (Number.isNaN(fmt.parseMoney(amount)) || fmt.parseMoney(amount) < 0)) return save.setError(mode === "points" ? "Points need to be a number." : "The commission needs to be a number.");
    if (office < -0.05) return save.setError("The payouts add up to more than the commission.");
    const body = {
      lines: reps.map(r => ({ kind: "rep", userId: r.userId, sharePct: reps.length === 1 ? 100 : n(r.sharePct), pct: n(r.pct) }))
        .concat(overs.map(o => ({ kind: "override", userId: o.userId, onUserId: o.onUserId, pct: n(o.pct) }))),
    };
    // The amount is sent only when it was changed here; a box left alone or left blank keeps what is on file.
    const amountChanged = String(amount).trim() !== "" && (String(amount).trim() !== startAmount || mode !== (rec.points != null ? "points" : "amount"));
    if (amountChanged && !anyPaid) body[mode === "points" ? "points" : "amount"] = n(amount);
    save.run(() => API.saveDealCommission(rec.dealId, body));
  };

  return (
    <Sheet eyebrow={rec.biz} title="Commission" onClose={onClose} onSubmit={submit} submitLabel="Save commission" busy={save.busy} error={save.error}>
      <div className="form-section">
        <span className="label">Commission on the deal</span>
        {anyPaid ? <div className="banner info" style={{ margin: "8px 0 0" }}>A payout has already been made, so the amount and that payout's rate are locked. Mark it unpaid to change them.</div> : null}
        <div className="comm-amount">
          <Segmented label="Entered as" value={mode} onChange={(m) => { if (!anyPaid && m !== mode) { setMode(m); setAmount(""); } }} options={[{ id: "amount", label: "Dollar amount" }, { id: "points", label: "Points" }]} />
          <Field label={mode === "points" ? "Points" : "Commission amount"} hint={mode === "points" ? `${n(amount) || 0} points on ${fmt.money(rec.fundedAmount)} funded = ${fmt.money(total)}` : rec.fundedAmount && total ? `${Math.round(total / rec.fundedAmount * 10000) / 100} points on ${fmt.money(rec.fundedAmount)} funded` : "What the deal pays the office."}>
            <TextInput value={amount} onChange={setAmount} inputMode="decimal" placeholder={mode === "points" ? "e.g. 8" : "$"} disabled={anyPaid} />
          </Field>
        </div>
      </div>
      <div className="form-section">
        <span className="label">Who is credited</span>
        {users === null ? <p className="dim" style={{ marginTop: 8 }}>Loading the team…</p> : (
          <>
            {!reps.length ? <p className="dim" style={{ margin: "8px 0" }}>Nobody is credited with this deal yet.</p> : null}
            {reps.map((r, i) => (
              <div className={`line-edit${reps.length > 1 ? " split" : ""}`} key={i}>
                <Field label={reps.length > 1 ? `Rep ${i + 1}` : "Rep"}><Select value={r.userId} onChange={x => pickRep(i, x)} options={options(r.userId, reps.map(x => x.userId))} disabled={r.locked} /></Field>
                {reps.length > 1 ? <Field label="Share of deal %"><TextInput value={r.sharePct} onChange={x => setRep(i, "sharePct", x)} inputMode="decimal" disabled={r.locked} /></Field> : null}
                <Field label="Payout %"><TextInput value={r.pct} onChange={x => setRep(i, "pct", x)} inputMode="decimal" disabled={r.locked} /></Field>
                <div className="line-out"><span className="tnum">{fmt.money(repAmount(r))}</span>
                  {!r.locked ? <button type="button" className="icon-btn" onClick={() => removeRep(i)} aria-label={`Remove ${r.userId ? nameOf(r.userId) : "this rep"}`}><Icon name="trash" size={15} /></button> : <span className="pill plain s-funded">Paid</span>}
                </div>
              </div>
            ))}
            {reps.length < 6 ? <button type="button" className="btn btn-sm" onClick={addRep} style={{ marginTop: 10 }}><Icon name="plus" size={13} />{reps.length ? "Split with another rep" : "Credit a rep"}</button> : null}
          </>
        )}
      </div>
      <div className="form-section">
        <span className="label">Overrides</span>
        <p className="hint" style={{ margin: "4px 0 2px" }}>A team leader's percentage of the commission on a rep's share. It comes out of the office's share, not the rep's, and the rep doesn't see it.</p>
        {overs.map((o, i) => (
          <div className={`line-edit${reps.length > 1 ? " split" : ""}`} key={i}>
            <Field label="Paid to"><Select value={o.userId} onChange={x => setOver(i, "userId", x)} options={options(o.userId, [o.onUserId].concat(overs.filter((x, j) => j !== i && x.onUserId === o.onUserId).map(x => x.userId)))} disabled={o.locked} /></Field>
            {reps.length > 1 ? <Field label="On the share of"><Select value={o.onUserId} onChange={x => setOver(i, "onUserId", x)} options={[{ value: "", label: "Choose…" }].concat(reps.filter(r => r.userId && r.userId !== o.userId).map(r => ({ value: r.userId, label: nameOf(r.userId) })))} disabled={o.locked} /></Field> : null}
            <Field label="Override %"><TextInput value={o.pct} onChange={x => setOver(i, "pct", x)} inputMode="decimal" disabled={o.locked} /></Field>
            <div className="line-out"><span className="tnum">{fmt.money(overAmount(o))}</span>
              {!o.locked ? <button type="button" className="icon-btn" onClick={() => setOvers(list => list.filter((_, j) => j !== i))} aria-label={`Remove the override for ${o.userId ? nameOf(o.userId) : "this person"}`}><Icon name="trash" size={15} /></button> : <span className="pill plain s-funded">Paid</span>}
            </div>
          </div>
        ))}
        {reps.some(r => r.userId) ? <button type="button" className="btn btn-sm" style={{ marginTop: 10 }} onClick={() => setOvers(list => list.concat([{ userId: "", onUserId: reps.length === 1 ? reps[0].userId : "", pct: "" }]))}><Icon name="plus" size={13} />Add an override</button> : null}
      </div>
      <div className="form-section">
        <div className="comm-sum">
          <span>Commission <b className="tnum">{fmt.money(total)}</b></span>
          <span>Paid out <b className="tnum">{fmt.money(Math.round((total - office) * 100) / 100)}</b></span>
          <span className={office < 0 ? "bad" : ""}>Office keeps <b className="tnum">{fmt.money(office)}</b></span>
        </div>
      </div>
    </Sheet>
  );
}

// ── On the deal file ────────────────────────────────────────────────────────
function DealCommissionCard({ deal, user, toast, confirm }) {
  const [rec, setRec] = useState(undefined);      // undefined = loading, null = nothing to show
  const [sheet, setSheet] = useState(null);
  const showing = useRef(deal.id); showing.current = deal.id;
  const load = useCallback(async () => {
    const id = deal.id;
    try { const r = await API.dealCommission(id); if (showing.current === id) setRec(r); } catch (e) { if (showing.current === id) setRec(null); }
  }, [deal.id]);
  const may = canOf(user);
  useEffect(() => { setRec(undefined); if (may.commissions) load(); }, [deal.id, deal.status, deal.amount, deal.funder, deal.repId, deal.fundedAt]);
  if (!may.commissions || !rec) return null;
  const canEdit = !!may.commissionEdit;
  const unfunded = deal.status !== "funded" ? <div className="banner info" style={{ margin: "12px 16px 0" }}>This deal is no longer marked Funded. What was recorded here is kept, and nothing on it counts as owed.</div> : null;

  const done = (msg) => (r) => { setSheet(null); if (r && r.dealId) setRec(r); else load(); toast(msg); };
  const unpay = (l) => confirm({
    title: "Mark this payout unpaid?", body: `${l.name}'s ${fmt.money(l.amount)} will go back to owed.`, confirmLabel: "Mark unpaid",
    onConfirm: async () => { await API.payCommissions([{ dealId: rec.dealId, lineId: l.id }], { paid: false }); await load(); toast("Marked unpaid"); },
  });
  const notReceived = () => confirm({
    title: "Mark the lender's payment not received?", body: `${rec.payer || "The lender"} will show as owing ${fmt.money(rec.amount)} again.`, confirmLabel: "Mark not received",
    onConfirm: async () => { setRec(await API.saveDealCommission(rec.dealId, { lender: { status: "owed" } })); toast("Marked not received"); },
  });
  const ls = lenderStatus(rec);
  const entered = fmt.num(rec.amount) > 0;

  if (rec.house === undefined) {          // the server sent this person's own lines only
    const mine = rec.lines.reduce((t, l) => t + fmt.num(l.amount), 0);
    return (
      <div className="card card-flush comm-card">
        <div className="card-head"><span className="label">Your commission</span><Pill status={ls.tone} label={ls.label} plain={ls.plain} /></div>
        {unfunded}
        {rec.lines.map(l => { const st = payoutStatus(rec, l); return (
          <div className="row" key={l.id}>
            <div className="grow"><div className="title">{lineWhat(l)}<Pill status={st.tone} label={st.label} plain={st.plain} /></div><div className="line">{lineTerms(l)}{entered ? ` · commission on the deal ${fmt.money(rec.amount)}` : ""}</div></div>
            <div className="right"><div className="big tnum">{entered ? fmt.money(l.amount) : "—"}</div></div>
          </div>
        ); })}
        {(rec.clawbacks || []).map(cb => cb.shares.map(x => (
          <div className="row" key={cb.id + x.lineId}>
            <div className="grow"><div className="title">Clawback{x.paid ? (x.owed > 0 ? <Pill status="declined" label={`You owe ${fmt.money(x.owed)}`} /> : <Pill status="funded" label="Paid back" />) : <Pill status="none" label="Came off your payout" plain />}</div>
              <div className="line">{rec.payer || "The lender"} took back commission on {fmt.day(cb.at)} ({reasonLabel(cb.reason).toLowerCase()}){x.recoveredAt ? ` · you paid back ${fmt.money(x.recoveredAmount)} on ${fmt.day(x.recoveredAt)}` : ""}</div></div>
            <div className="right"><div className="big tnum">−{fmt.money(x.amount)}</div></div>
          </div>
        )))}
        {rec.lines.length > 1 ? <div className="card-foot">Total for you <b className="tnum">{fmt.money(mine)}</b></div> : null}
      </div>
    );
  }
  const clawbacks = rec.clawbacks || [];
  const left = cents(fmt.num(rec.amount) - fmt.num(rec.clawed));
  const takeOff = (cb) => confirm({
    title: "Take this clawback off?", body: `The ${fmt.money(cb.amount)} clawback on ${fmt.day(cb.at)} will be removed, and everyone's payouts go back to what they were.`, confirmLabel: "Take it off",
    onConfirm: async () => { setRec(await API.deleteClawback(rec.dealId, cb.id)); toast("Clawback taken off"); },
  });
  const unrecover = (cb, x) => confirm({
    title: "Mark this not paid back?", body: `${x.name} will owe ${fmt.money(x.amount)} again.`, confirmLabel: "Mark not paid back",
    onConfirm: async () => { await API.recoverClawbacks([{ dealId: rec.dealId, clawbackId: cb.id, lineId: x.lineId }], { recovered: false }); await load(); toast("Marked not paid back"); },
  });
  return (
    <div className="card card-flush comm-card">
      <div className="card-head">
        <span className="label">Commission</span>
        {canEdit && !clawbacks.length ? <button className="btn btn-sm" onClick={() => setSheet({ kind: "edit" })}><Icon name="edit" size={14} />{entered ? "Edit commission" : "Enter commission"}</button> : null}
      </div>
      {unfunded}
      <div className="comm-top">
        <div>
          <div className="serif tnum comm-big">{entered ? fmt.money(rec.amount) : "Not entered yet"}</div>
          <div className="line">{entered ? `${rec.points != null ? rec.points : Math.round(rec.amount / (rec.fundedAmount || 1) * 10000) / 100} points on ${fmt.money(rec.fundedAmount)} funded` : "Enter what this deal pays the office to work out everyone's payout."}</div>
        </div>
        <div className="comm-lender">
          <Pill status={ls.tone} label={ls.label} plain={ls.plain} />
          <div className="line">{rec.inHouse ? "Nothing to collect from a lender." : rec.lender.status === "received" ? `${fmt.money(rec.lender.receivedAmount)} from ${rec.payer || "the lender"}${fmt.num(rec.lender.receivedAmount) < fmt.num(rec.amount) - 0.005 ? ` · ${fmt.money(Math.round((rec.amount - rec.lender.receivedAmount) * 100) / 100)} short` : ""}${rec.lender.note ? " · " + rec.lender.note : ""}` : `From ${rec.payer || "the lender"}`}</div>
          {canEdit && !rec.inHouse && entered ? (rec.lender.status === "received"
            ? <button className="link-btn" onClick={notReceived}>Mark not received</button>
            : <button className="btn btn-sm btn-primary" onClick={() => setSheet({ kind: "received" })}>Mark received</button>) : null}
        </div>
      </div>
      {!rec.lines.length ? <div className="card-body dim" style={{ fontSize: 13.5, borderTop: "1px solid var(--rule-soft)" }}>Nobody is credited with this deal. Assign a rep to the deal, or choose one under {entered ? "Edit" : "Enter"} commission.</div> : null}
      {rec.lines.map(l => { const st = payoutStatus(rec, l); return (
        <div className="row" key={l.id}>
          <Avatar name={l.name} size="sm" />
          <div className="grow"><div className="title">{l.name}<Pill status={st.tone} label={st.label} plain={st.plain} /></div><div className="line">{lineWhat(l)} · {lineTerms(l)}{l.paidNote ? " · " + l.paidNote : ""}</div></div>
          <div className="right"><div className="big tnum">{fmt.money(l.paidAt ? l.paidAmount : l.net)}</div>{fmt.num(l.clawed) > 0 ? <div className="line tnum">{fmt.money(l.amount)} less {fmt.money(l.clawed)} clawed</div> : null}</div>
          {canEdit ? <div className="row-actions">
            {l.paidAt ? (fmt.num(l.clawed) > 0 ? null : <button className="btn btn-sm" onClick={() => unpay(l)} aria-label={`Mark ${l.name}'s payout unpaid`}>Undo</button>)
              : fmt.num(l.net) > 0 ? <button className="btn btn-sm" onClick={() => setSheet({ kind: "pay", items: [{ dealId: rec.dealId, lineId: l.id, biz: rec.biz, name: l.name, kind: l.kind, onName: l.onName, amount: l.net, lenderStatus: rec.lender.status }] })} aria-label={`Mark ${l.name}'s payout paid`}>Mark paid</button> : null}
          </div> : null}
        </div>
      ); })}
      {clawbacks.length || (canEdit && entered && left > 0) ? (
        <div className="comm-claw">
          <div className="card-head"><span className="label">Clawbacks{clawbacks.length ? ` · ${fmt.money(rec.clawed)} taken back` : ""}</span>
            {canEdit && entered && left > 0 ? <button className="btn btn-sm" onClick={() => setSheet({ kind: "clawback" })}><Icon name="alert" size={14} />Record clawback</button> : null}</div>
          {!clawbacks.length ? <div className="card-body dim" style={{ fontSize: 13.5 }}>If {rec.payer || "the lender"} takes back commission on this deal, record it here: each person's part comes off their payout, or is owed back if they've been paid.</div> : null}
          {clawbacks.map(cb => (
            <div key={cb.id} className="claw">
              <div className="row">
                <div className="grow"><div className="title">{fmt.day(cb.at)} · {reasonLabel(cb.reason)}</div><div className="line">{rec.payer || "The lender"} took back {fmt.money(cb.amount)}{cb.note ? " · " + cb.note : ""} · office's part {fmt.money(cb.office)}</div></div>
                <div className="right"><div className="big tnum">−{fmt.money(cb.amount)}</div></div>
                {canEdit && !cb.shares.some(x => x.recoveredAt) ? <div className="row-actions"><button className="btn btn-sm" onClick={() => takeOff(cb)} aria-label={`Take off the ${fmt.money(cb.amount)} clawback`}>Take off</button></div> : null}
              </div>
              {cb.shares.map(x => (
                <div className="row sub-row" key={x.lineId}>
                  <Avatar name={x.name} size="sm" />
                  <div className="grow"><div className="title">{x.name}{x.kind === "override" ? " (override)" : ""}
                    {!x.paid ? <Pill status="none" label="Came off the payout" plain /> : x.owed > 0 ? <Pill status="declined" label={`Owes ${fmt.money(x.owed)}`} /> : <Pill status="funded" label={`Paid back ${fmt.day(x.recoveredAt)}`} />}</div>
                    {x.recoveredAt && x.owed > 0 ? <div className="line">{fmt.money(x.recoveredAmount)} paid back on {fmt.day(x.recoveredAt)}</div> : x.recoveredNote ? <div className="line">{x.recoveredNote}</div> : null}</div>
                  <div className="right"><span className="tnum">{fmt.money(x.amount)}</span></div>
                  {canEdit && x.paid ? <div className="row-actions">{x.owed > 0
                    ? <button className="btn btn-sm" onClick={() => setSheet({ kind: "recover", items: [{ dealId: rec.dealId, clawbackId: cb.id, lineId: x.lineId, biz: rec.biz, name: x.name, owed: x.owed, recovered: x.recoveredAmount || 0, at: cb.at }] })}>Paid back</button>
                    : <button className="btn btn-sm" onClick={() => unrecover(cb, x)}>Undo</button>}</div> : null}
                </div>
              ))}
            </div>
          ))}
        </div>
      ) : null}
      {entered ? <div className="card-foot">Office keeps <b className="tnum">{fmt.money(rec.house)}</b> after payouts{fmt.num(rec.clawed) > 0 ? " and clawbacks" : ""}{rec.lines.some(l => l.kind === "override") ? ". Overrides and this figure are visible to Admins only." : "."}{clawbacks.length && canEdit ? " Take the clawback off to change the amount or who is credited." : ""}</div> : null}
      {sheet ? (
        <Portal>
          {sheet.kind === "edit" ? <CommissionSheet rec={rec} onClose={() => setSheet(null)} onSaved={done("Commission saved")} /> : null}
          {sheet.kind === "received" ? <ReceivedSheet rec={rec} onClose={() => setSheet(null)} onSaved={done("Marked received")} /> : null}
          {sheet.kind === "pay" ? <PaySheet items={sheet.items} onClose={() => setSheet(null)} onSaved={done("Marked paid")} /> : null}
          {sheet.kind === "clawback" ? <ClawbackSheet rec={rec} onClose={() => setSheet(null)} onSaved={done("Clawback recorded")} /> : null}
          {sheet.kind === "recover" ? <RecoverSheet items={sheet.items} onClose={() => setSheet(null)} onSaved={() => { setSheet(null); load(); toast("Marked paid back"); }} /> : null}
        </Portal>
      ) : null}
    </div>
  );
}

// ── One person's report ─────────────────────────────────────────────────────
function PersonFigures({ p, monthLabel }) {
  const cell = (k, v, s) => <div className="fig"><span className="k">{k}</span><span className="v serif tnum">{v}</span><span className="s">{s}</span></div>;
  return (
    <div className="figs">
      {cell(`Funded in ${monthLabel}`, fmt.moneyShort(p.fundedMonth), `${p.dealsMonth} ${p.dealsMonth === 1 ? "deal" : "deals"} · all time ${fmt.moneyShort(p.fundedTotal)} on ${p.dealsTotal}`)}
      {cell(`Commission in ${monthLabel}`, fmt.money(p.earnedMonth), `All time ${fmt.money(p.earnedTotal)}${p.overrideTotal ? ` · ${fmt.money(p.overrideTotal)} of it overrides` : ""}`)}
      {cell("Paid so far", fmt.money(p.paidTotal), p.paidMonth ? `${fmt.money(p.paidMonth)} paid in ${monthLabel}` : `Nothing paid in ${monthLabel}`)}
      {cell("Still owed", fmt.money(p.owed), p.owed ? "Not yet paid out" : "All paid up")}
      {p.owesBack || p.clawedTotal ? cell("Owes back", fmt.money(p.owesBack || 0), `Clawbacks: ${fmt.money(p.clawedTotal || 0)} all time${p.clawedMonth ? `, ${fmt.money(p.clawedMonth)} in ${monthLabel}` : ""}`) : null}
    </div>
  );
}
// A row that opens the deal when this person can open deals (a Bookkeeper can't), else plain.
function DealRow({ dealId, go, after, children }) {
  return go ? <button className="row row-btn" onClick={() => { go("deals", dealId); after && after(); }}>{children}</button> : <div className="row">{children}</div>;
}
function PersonLines({ userId, records, go, onNavigate }) {
  const rows = [];
  for (const r of records) for (const l of r.lines) if (l.userId === userId) rows.push({ r, l });
  if (!rows.length) return <div className="card-body dim" style={{ fontSize: 13.5 }}>No funded deals credited yet.</div>;
  return rows.map(({ r, l }) => { const st = payoutStatus(r, l); return (
    <DealRow key={r.dealId + l.id} dealId={r.dealId} go={go} after={onNavigate}>
      <span className="grow">
        <span className="title">{r.biz}<Pill status={st.tone} label={st.label} plain={st.plain} />{r.stillFunded === false ? <span className="pill plain">No longer funded</span> : null}</span>
        <span className="line">{r.fundedAt ? `Funded ${fmt.date(r.fundedAt)} · ` : ""}{fmt.money(r.fundedAmount)}{r.payer ? ` by ${r.payer}` : ""} · {lineWhat(l)} · {lineTerms(l)}{fmt.num(l.clawed) > 0 ? ` · ${fmt.money(l.clawed)} clawed back` : ""}</span>
      </span>
      <span className="right"><span className="big tnum">{fmt.num(r.amount) > 0 ? fmt.money(l.paidAt ? l.paidAmount : fmt.num(l.net != null ? l.net : l.amount)) : "—"}</span></span>
    </DealRow>
  ); });
}
// What people owe back from clawbacks, grouped by person.
function OwedBackList({ items, canEdit, go, onRecover }) {
  if (!items.length) return <div className="card"><div className="card-body dim" style={{ fontSize: 13.5 }}>Nobody owes anything back.</div></div>;
  const groups = [];
  for (const i of items) { let g = groups.find(x => x.userId === i.userId); if (!g) groups.push(g = { userId: i.userId, name: i.name, items: [] }); g.items.push(i); }
  return groups.map(g => (
    <div className="card card-flush" key={g.userId} style={{ marginBottom: 12 }}>
      <div className="card-head">
        <span className="who-line"><Avatar name={g.name} size="sm" /><b>{g.name}</b>{" "}<span className="dim">owes back <b className="tnum">{fmt.money(g.items.reduce((t, i) => t + i.owed, 0))}</b></span></span>
        {canEdit && g.items.length > 1 ? <button className="btn btn-sm" onClick={() => onRecover(g.items)}>All paid back</button> : null}
      </div>
      {g.items.map(i => (
        <div className="row" key={i.dealId + i.clawbackId + i.lineId}>
          <div className="grow">
            <div className="title">{go ? <button className="link-btn" onClick={() => go("deals", i.dealId)}>{i.biz}</button> : i.biz}<Pill status="declined" label={reasonLabel(i.reason)} /></div>
            <div className="line">{i.kind === "override" ? `Override on ${i.onName || "a rep"} · ` : ""}{i.payer || "The lender"} took it back {fmt.day(i.at)}{i.recovered ? ` · ${fmt.money(i.recovered)} of ${fmt.money(i.amount)} paid back` : ""}</div>
          </div>
          <div className="right"><div className="big tnum">{fmt.money(i.owed)}</div></div>
          {canEdit ? <div className="row-actions"><button className="btn btn-sm" onClick={() => onRecover([i])}>Paid back</button></div> : null}
        </div>
      ))}
    </div>
  ));
}
function PersonSheet({ person, data, go, onClose }) {
  const closeBtn = useRef(null);
  useEffect(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", onKey);
    const prev = document.activeElement;
    if (closeBtn.current) closeBtn.current.focus();
    return () => { document.removeEventListener("keydown", onKey); if (prev && prev.focus && document.contains(prev)) prev.focus(); };
  }, []);
  const rates = [person.payoutPct != null ? `${pctText(person.payoutPct)} payout` : "No payout rate set"].concat((person.overrides || []).map(o => `${o.name} earns ${pctText(o.pct)} override`));
  return (
    <>
      <div className="scrim" onClick={onClose} />
      <div className="sheet wide" role="dialog" aria-modal="true" aria-label={`${person.name}: funded and commission`}>
        <div className="sheet-head">
          <div><div className="label">{person.role || "Team"} · {rates.join(" · ")}</div><h2>{person.name}</h2></div>
          <button type="button" className="icon-btn" onClick={onClose} aria-label="Close" ref={closeBtn}><Icon name="x" /></button>
        </div>
        <div className="sheet-body" style={{ padding: 16 }}>
          <PersonFigures p={person} monthLabel={data.monthLabel.split(" ")[0]} />
          <div className="card card-flush" style={{ marginTop: 14 }}>
            <div className="card-head"><span className="label">Deals and payouts</span></div>
            <PersonLines userId={person.userId} records={data.records} go={go} onNavigate={onClose} />
          </div>
        </div>
      </div>
    </>
  );
}

// ── The Commissions page ────────────────────────────────────────────────────
function useCommissions(month) {
  const [data, setData] = useState(null);
  const [error, setError] = useState("");
  const latest = useRef(0);
  const load = useCallback(async () => {
    const mine = ++latest.current;
    try { const d = await API.commissions(month); if (mine === latest.current) { setData(d); setError(""); } }
    catch (err) { if (mine === latest.current && err.status !== 401) setError(err.message); }
  }, [month]);
  useEffect(() => { load(); }, [month]);
  return { data, error, reload: load };
}
function MonthPicker({ month, label, onChange }) {
  const now = todayLocal().slice(0, 7);
  const step = (by) => { const [y, m] = (month || now).split("-").map(Number); const d = new Date(Date.UTC(y, m - 1 + by, 1)); onChange(`${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, "0")}`); };
  return (
    <div className="monthpick" role="group" aria-label="Month">
      <button type="button" className="icon-btn" onClick={() => step(-1)} aria-label="Previous month"><Icon name="back" size={15} /></button>
      <b>{label}</b>
      <button type="button" className="icon-btn" onClick={() => step(1)} disabled={(month || now) >= now} aria-label="Next month"><span style={{ display: "grid", transform: "rotate(180deg)" }}><Icon name="back" size={15} /></span></button>
    </div>
  );
}

function CommissionsView({ user, toast, confirm, go }) {
  const [month, setMonth] = useState(null);
  const { data, error, reload } = useCommissions(month);
  const [tab, setTab] = useState(null);
  const [sheet, setSheet] = useState(null);

  if (error && !data) return <main className="workspace single"><div className="page"><div className="banner" role="alert">Couldn't load commissions: {error} <button className="link-btn" onClick={reload}>Try again</button></div></div></main>;
  if (!data) return <main className="workspace single"><div className="page"><div className="empty"><p>Loading commissions…</p></div></div></main>;
  const done = (msg) => () => { setSheet(null); reload(); toast(msg); };
  const moreNote = data.recordsTotal > data.recordsShown ? <div className="card-foot">Showing the {data.recordsShown} most recent of {data.recordsTotal}. The figures above cover all of them.</div> : null;

  // What the server sent decides the view, so a role changed mid-session can't show the wrong one.
  if (data.scope !== "all") {
    const me = data.people[0];
    return (
      <main className="workspace single">
        <div className="page">
          <div className="page-head">
            <div><h1>My commissions</h1><p>Deals credited to you, what they pay you, and what has been paid.{me.payoutPct != null ? ` Your payout rate is ${pctText(me.payoutPct)} of the commission.` : ""}</p></div>
            <div className="page-tools"><MonthPicker month={data.month} label={data.monthLabel} onChange={setMonth} /></div>
          </div>
          <PersonFigures p={me} monthLabel={data.monthLabel.split(" ")[0]} />
          <div className="card card-flush" style={{ marginTop: 16 }}>
            <div className="card-head"><span className="label">Your deals and payouts: {data.monthLabel.split(" ")[0]}, and anything not yet paid</span></div>
            <PersonLines userId={me.userId} records={data.records} go={go} />
            {moreNote}
          </div>
          {(data.owedBack || []).length ? <div style={{ marginTop: 16 }}><div className="label" style={{ marginBottom: 8 }}>Clawbacks you owe back</div><OwedBackList items={data.owedBack} canEdit={false} go={go} /></div> : null}
        </div>
      </main>
    );
  }

  const t = data.totals, mLabel = data.monthLabel.split(" ")[0];
  const canEdit = data.canEdit !== false;                     // a Bookkeeper reads, and exports
  const open = data.canOpenDeals === false ? null : go;       // and doesn't open deals
  const owedBack = data.owedBack || [];
  const current = tab || (data.missing.length ? "setup" : data.receivables.length ? "lenders" : data.payables.length ? "team" : "people");
  const tabs = [
    data.missing.length ? { id: "setup", label: "Needs setup", n: data.missing.length } : null,
    { id: "lenders", label: "Owed by lenders", n: data.receivables.length },
    { id: "team", label: "Owed to the team", n: data.payables.length },
    owedBack.length || t.clawedTotal ? { id: "back", label: "Owed back", n: owedBack.length } : null,
    { id: "people", label: "By person" },
    { id: "deals", label: "Deals", n: data.records.length },
  ].filter(Boolean);
  const exportCsv = async () => { try { await API.exportCommissions(); toast("Downloaded commissions.csv"); } catch (err) { toast(err.message, true); } };
  const byPerson = [];
  for (const p of data.payables) { let g = byPerson.find(x => x.userId === p.userId); if (!g) byPerson.push(g = { userId: p.userId, name: p.name, items: [] }); g.items.push(p); }
  const fig = (k, v, s, tone) => <div className={`fig${tone ? " t-" + tone : ""}`}><span className="k">{k}</span><span className="v serif tnum">{v}</span><span className="s">{s}</span></div>;

  return (
    <main className="workspace single">
      <div className="page wide">
        <div className="page-head">
          <div><h1>Commissions</h1><p>What lenders owe the office, what the office owes the team, clawbacks, and what each person has funded and earned.{canEdit ? "" : " Read-only."}</p></div>
          <div className="page-tools"><button className="btn" onClick={exportCsv}><Icon name="download" size={14} />Export CSV</button><MonthPicker month={data.month} label={data.monthLabel} onChange={setMonth} /></div>
        </div>
        <div className="figs">
          {fig(`Commission in ${mLabel}`, fmt.money(t.commissionMonth), `${t.dealsMonth} ${t.dealsMonth === 1 ? "deal" : "deals"} · ${fmt.moneyShort(t.fundedMonth)} funded`)}
          {fig("Owed by lenders", fmt.money(t.owedByLenders), data.receivables.length ? `${data.receivables.length} ${data.receivables.length === 1 ? "deal" : "deals"} not yet received` : "Nothing outstanding", data.receivables.some(r => r.days >= 30) ? "bad" : null)}
          {fig("Owed to the team", fmt.money(t.owedToTeam), data.payables.length ? `${data.payables.length} ${data.payables.length === 1 ? "payout" : "payouts"} to make` : "Everyone is paid up")}
          {fig(`Office share in ${mLabel}`, fmt.money(t.officeMonth), `After ${fmt.money(t.payoutsMonth)} in payouts${t.clawedMonth ? ` and ${fmt.money(t.clawedMonth)} clawed back` : ""}`)}
          {t.clawedTotal || t.owedBack ? fig("Owed back to the office", fmt.money(t.owedBack), `Clawbacks: ${fmt.money(t.clawedTotal)} all time${t.clawedMonth ? `, ${fmt.money(t.clawedMonth)} in ${mLabel}` : ""}`, t.owedBack ? "bad" : null) : null}
        </div>
        <div className="seg comm-tabs" role="group" aria-label="Show">
          {tabs.map(x => <button type="button" key={x.id} aria-pressed={current === x.id} onClick={() => setTab(x.id)}>{x.label}{x.n != null ? <span className="n tnum">{x.n}</span> : null}</button>)}
        </div>

        {current === "setup" ? (
          <div className="card card-flush">
            <div className="card-head"><span className="label">Funded deals that need a commission entered or a rep credited</span></div>
            {data.missing.map(x => (
              <DealRow key={x.dealId} dealId={x.dealId} go={open}>
                <span className="grow"><span className="title">{x.biz}</span><span className="line">{[x.noAmount ? "No commission entered" : "", x.noRep ? "No rep credited" : ""].filter(Boolean).join(" · ")}{x.fundedAt ? ` · funded ${fmt.date(x.fundedAt)}` : ""}{x.payer ? ` by ${x.payer}` : ""}</span></span>
                <span className="right"><span className="big tnum">{fmt.money(x.fundedAmount)}</span><span className="line" style={{ display: "block" }}>funded</span></span>
              </DealRow>
            ))}
          </div>
        ) : null}

        {current === "lenders" ? (
          <div className="card card-flush">
            <div className="card-head"><span className="label">Commissions lenders haven't paid yet, oldest first</span></div>
            {!data.receivables.length ? <div className="card-body dim" style={{ fontSize: 13.5 }}>No lender owes the office a commission right now.</div> : null}
            {data.receivables.map(r => (
              <div className="row" key={r.dealId}>
                <div className="grow">
                  <div className="title">{open ? <button className="link-btn" onClick={() => go("deals", r.dealId)}>{r.biz}</button> : r.biz}{r.short ? <Pill status="declined" label="Paid short" /> : null}{r.days >= 30 ? <Pill status="declined" label={`${r.days} days`} /> : null}</div>
                  <div className="line">{r.payer || "Lender not recorded"}{r.short ? ` · paid ${fmt.money(r.received)} of ${fmt.money(r.commission)}` : ""}{r.fundedAt ? ` · funded ${fmt.date(r.fundedAt)}` : ""}{r.days != null && r.days < 30 ? ` · ${r.days} ${r.days === 1 ? "day" : "days"} ago` : ""}</div>
                </div>
                <div className="right"><div className="big tnum">{fmt.money(r.amount)}</div></div>
                {canEdit ? <div className="row-actions">{r.short
                  ? <button className="btn btn-sm" onClick={() => go("deals", r.dealId)} aria-label={`Open ${r.biz} to settle the short payment`}>Open deal</button>
                  : <button className="btn btn-sm btn-primary" onClick={() => setSheet({ kind: "received", rec: { dealId: r.dealId, biz: r.biz, payer: r.payer, amount: r.amount } })} aria-label={`Mark the ${r.biz} commission received`}>Mark received</button>}</div> : null}
              </div>
            ))}
          </div>
        ) : null}

        {current === "team" ? (
          !byPerson.length ? <div className="card"><div className="card-body dim" style={{ fontSize: 13.5 }}>Everyone is paid up.</div></div> : byPerson.map(g => {
            const ready = g.items.filter(i => i.lenderStatus !== "owed");
            return (
              <div className="card card-flush" key={g.userId} style={{ marginBottom: 12 }}>
                <div className="card-head">
                  <span className="who-line"><Avatar name={g.name} size="sm" /><b>{g.name}</b>{" "}<span className="dim">is owed <b className="tnum">{fmt.money(g.items.reduce((s, i) => s + i.amount, 0))}</b></span></span>
                  {canEdit ? <button className="btn btn-sm btn-primary" onClick={() => setSheet({ kind: "pay", items: g.items })} aria-label={`Pay ${g.name} everything owed: ${fmt.money(g.items.reduce((s, i) => s + i.amount, 0))}`}>Pay all {g.items.length > 1 ? g.items.length : ""}</button> : null}
                </div>
                {g.items.map(i => (
                  <div className="row" key={i.dealId + i.lineId}>
                    <div className="grow">
                      <div className="title">{open ? <button className="link-btn" onClick={() => go("deals", i.dealId)}>{i.biz}</button> : i.biz}{i.lenderStatus === "owed" ? <Pill status="new" label="Waiting on lender" /> : <Pill status="submitted" label="Ready to pay" />}</div>
                      <div className="line">{lineWhat(i)}{i.fundedAt ? ` · funded ${fmt.date(i.fundedAt)}` : ""}{i.payer ? ` by ${i.payer}` : ""}{i.clawed ? ` · ${fmt.money(i.clawed)} clawed back` : ""}</div>
                    </div>
                    <div className="right"><div className="big tnum">{fmt.money(i.amount)}</div></div>
                    {canEdit ? <div className="row-actions"><button className="btn btn-sm" onClick={() => setSheet({ kind: "pay", items: [i] })} aria-label={`Mark ${g.name}'s payout on ${i.biz} paid`}>Mark paid</button></div> : null}
                  </div>
                ))}
                {canEdit && ready.length && ready.length < g.items.length ? <div className="card-foot">{fmt.money(ready.reduce((s, i) => s + i.amount, 0))} of this is on deals the lender has already paid. <button className="link-btn" onClick={() => setSheet({ kind: "pay", items: ready })} aria-label={`Pay ${g.name} only what the lender has already paid`}>Pay just those</button></div> : null}
              </div>
            );
          })
        ) : null}

        {current === "back" ? <OwedBackList items={owedBack} canEdit={canEdit} go={open} onRecover={(items) => setSheet({ kind: "recover", items })} /> : null}

        {current === "people" ? (
          <div className="card">
            <div className="table-wrap">
              <table className="list">
                <thead><tr><th>Team member</th><th className="num">Funded in {mLabel}</th><th className="num">Funded all time</th><th className="num">Commission in {mLabel}</th><th className="num">Commission all time</th><th className="num">Paid</th><th className="num">Owed</th>{t.clawedTotal ? <th className="num">Owes back</th> : null}</tr></thead>
                <tbody>
                  {data.people.map(p => (
                    <tr key={p.userId}>
                      <td><div className="who"><Avatar name={p.name} size="sm" /><div><button className="link-btn strong" onClick={() => setSheet({ kind: "person", person: p })}>{p.name}</button><span>{p.payoutPct != null ? `${pctText(p.payoutPct)} payout` : "No rate set"}{p.overrides.length ? ` · override: ${p.overrides.map(o => `${o.name} ${pctText(o.pct)}`).join(", ")}` : ""}</span></div></div></td>
                      <td className="num tnum" data-label={`Funded in ${mLabel}`}>{fmt.money(p.fundedMonth)}<span className="sub">{p.dealsMonth} {p.dealsMonth === 1 ? "deal" : "deals"}</span></td>
                      <td className="num tnum" data-label="Funded all time">{fmt.money(p.fundedTotal)}<span className="sub">{p.dealsTotal} {p.dealsTotal === 1 ? "deal" : "deals"}</span></td>
                      <td className="num tnum" data-label={`Commission in ${mLabel}`}>{fmt.money(p.earnedMonth)}{p.overrideMonth ? <span className="sub">{fmt.money(p.overrideMonth)} overrides</span> : null}</td>
                      <td className="num tnum" data-label="Commission all time">{fmt.money(p.earnedTotal)}{p.overrideTotal ? <span className="sub">{fmt.money(p.overrideTotal)} overrides</span> : null}</td>
                      <td className="num tnum" data-label="Paid">{fmt.money(p.paidTotal)}</td>
                      <td className="num tnum" data-label="Owed">{p.owed ? <b>{fmt.money(p.owed)}</b> : fmt.money(0)}</td>
                      {t.clawedTotal ? <td className="num tnum" data-label="Owes back">{p.owesBack ? <b className="bad">{fmt.money(p.owesBack)}</b> : fmt.money(0)}{p.clawedTotal ? <span className="sub">{fmt.money(p.clawedTotal)} clawed</span> : null}</td> : null}
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
            <div className="card-foot">All time: {fmt.money(t.commissionTotal)} in commission on {fmt.money(t.fundedTotal)} funded across {t.dealsTotal} {t.dealsTotal === 1 ? "deal" : "deals"}; {t.clawedTotal ? `${fmt.money(t.clawedTotal)} clawed back; ` : ""}{fmt.money(t.payoutsTotal)} to the team, {fmt.money(t.officeTotal)} to the office.{t.undated ? ` ${t.undated} funded ${t.undated === 1 ? "deal has" : "deals have"} no funding date and count in the all-time figures only.` : ""}</div>
          </div>
        ) : null}

        {current === "deals" ? (
          <div className="card card-flush">
            <div className="card-head"><span className="label">Deals funded in {mLabel}, and any from earlier with something still outstanding</span></div>
            {!data.records.length ? <div className="card-body dim" style={{ fontSize: 13.5 }}>No funded deals in {mLabel}, and nothing outstanding.</div> : null}
            {data.records.map(r => { const ls = lenderStatus(r); const unpaid = r.lines.filter(l => !l.paidAt && fmt.num(l.net != null ? l.net : l.amount) > 0).length; return (
              <DealRow key={r.dealId} dealId={r.dealId} go={open}>
                <span className="grow">
                  <span className="title">{r.biz}<Pill status={ls.tone} label={ls.label} plain={ls.plain} />{fmt.num(r.amount) > 0 ? (unpaid ? <Pill status="submitted" label={`${unpaid} to pay`} /> : r.lines.length ? <Pill status="funded" label="Team paid" /> : null) : null}{fmt.num(r.clawed) > 0 ? <Pill status="declined" label={`${fmt.money(r.clawed)} clawed back`} /> : null}{r.stillFunded === false ? <span className="pill plain">No longer funded</span> : null}</span>
                  <span className="line">{r.fundedAt ? `Funded ${fmt.date(r.fundedAt)} · ` : ""}{fmt.money(r.fundedAmount)}{r.payer ? ` by ${r.payer}` : ""} · {r.lines.filter(l => l.kind === "rep").map(l => l.name).join(", ") || "no rep credited"}{fmt.num(r.amount) > 0 ? ` · office keeps ${fmt.money(r.house)}` : ""}</span>
                </span>
                <span className="right"><span className="big tnum">{fmt.num(r.amount) > 0 ? fmt.money(r.amount) : "—"}</span></span>
              </DealRow>
            ); })}
            {moreNote}
          </div>
        ) : null}
      </div>
      {sheet && sheet.kind === "received" ? <ReceivedSheet rec={sheet.rec} onClose={() => setSheet(null)} onSaved={done("Marked received")} /> : null}
      {sheet && sheet.kind === "pay" ? <PaySheet items={sheet.items} onClose={() => setSheet(null)} onSaved={done("Marked paid")} /> : null}
      {sheet && sheet.kind === "person" ? <PersonSheet person={sheet.person} data={data} go={open} onClose={() => setSheet(null)} /> : null}
      {sheet && sheet.kind === "recover" ? <RecoverSheet items={sheet.items} onClose={() => setSheet(null)} onSaved={done("Marked paid back")} /> : null}
    </main>
  );
}

Object.assign(window, { CommissionsView, DealCommissionCard, PersonSheet, pctText });
