/* Payroll — run-payroll workflow built on the real two-draw model.
   Draw 1 (50%) pays on deposit/sale; Draw 2 (50%) pays on completion.
   Select the draws to include this cycle → see each rep's paycheck →
   run payroll (marks them paid). Pulls from the past-90-day sales. */

const PR = window.Ds1Threshold_e046d3;

function Payroll({ viewer }) {
  const api = window.OneDayPayroll;
  const me = viewer || { role: "owner", repName: null };
  const isRep = me.role === "rep";
  const canRun = !isRep; // owner & manager can approve/run; reps are read-only
  const mineOnly = (arr) => isRep ? arr.filter((x) => x.rep === me.repName) : arr;
  const [, force] = React.useReducer((x) => x + 1, 0);
  const [picked, setPicked] = React.useState(() => new Set());
  const [tab, setTab] = React.useState("run"); // run | sales | import
  const [importResult, setImportResult] = React.useState(null);
  const [importErr, setImportErr] = React.useState("");
  const [salesSort, setSalesSort] = React.useState({ key: "saleMs", dir: "desc" });
  const fileRef = React.useRef(null);
  const salesRef = React.useRef(null);
  const periods = api.listPeriods();
  const [periodId, setPeriodId] = React.useState(""); // default: all open periods (everything due)
  const period = periods.find((p) => p.id === periodId);
  const [completedOnly, setCompletedOnly] = React.useState(() => localStorage.getItem("od_completed_only") === "1");
  const toggleCompletedOnly = () => { const v = !completedOnly; setCompletedOnly(v); localStorage.setItem("od_completed_only", v ? "1" : "0"); };

  const draws = mineOnly(api.payableDraws(periodId)).filter((d) => !completedOnly || d.installed);
  const [drawSort, setDrawSort] = React.useState({ key: "recdate", dir: "asc" }); // by pay date
  const allSales = api.load();
  const sales = mineOnly(allSales);
  // Totals: global for owner/manager; scoped to the rep's own jobs otherwise.
  const t = isRep ? (function () {
    const r2 = api.round2; const own = sales.filter((x) => !x.exempt);
    return {
      paid: r2(own.reduce((s, x) => s + (x.draw1Paid ? x.draw1 : 0) + (x.draw2Paid ? x.draw2 : 0), 0)),
      depositDue: r2(own.filter((x) => !x.draw1Paid).reduce((s, x) => s + x.draw1, 0)),
      completionDue: r2(own.filter((x) => x.installed && !x.draw2Paid).reduce((s, x) => s + x.draw2, 0)),
      heldUninstalled: r2(own.filter((x) => !x.installed && !x.draw2Paid).reduce((s, x) => s + x.draw2, 0)),
    };
  })() : api.totals();

  const pickedList = draws.filter((d) => picked.has(d.saleId + ":" + d.kind));
  // Per-rep commission rollup across the whole dataset (owner/manager view).
  const byRep = (function () {
    const m = {};
    allSales.forEach((x) => {
      const k = x.rep || "—";
      const r = m[k] || (m[k] = { rep: k, earned: 0, paid: 0, due: 0, total: 0, exempt: 0 });
      r.total += 1;
      if (x.exempt) { r.exempt += 1; return; }
      r.earned += x.commission;
      r.paid += (x.draw1Paid ? x.draw1 : 0) + (x.draw2Paid ? x.draw2 : 0);
      r.due += (x.draw1Paid ? 0 : x.draw1) + (x.installed && !x.draw2Paid ? x.draw2 : 0);
    });
    return Object.values(m).map((r) => ({ ...r, earned: api.round2(r.earned), paid: api.round2(r.paid), due: api.round2(r.due), allExempt: r.exempt === r.total && r.total > 0 })).sort((a, b) => b.earned - a.earned);
  })();
  const isPicked = (d) => picked.has(d.saleId + ":" + d.kind);
  const toggle = (d) => setPicked((prev) => { const n = new Set(prev); const k = d.saleId + ":" + d.kind; n.has(k) ? n.delete(k) : n.add(k); return n; });
  const pickAll = () => setPicked(new Set(draws.map((d) => d.saleId + ":" + d.kind)));
  const clearAll = () => setPicked(new Set());

  // Per-rep paycheck from the picked draws.
  const reps = [...new Set(draws.map((d) => d.rep))];
  const checks = reps.map((rep) => {
    const mine = pickedList.filter((d) => d.rep === rep);
    return { rep, deposit: mine.filter((d) => d.kind === "deposit").reduce((s, d) => s + d.amount, 0), completion: mine.filter((d) => d.kind === "completion").reduce((s, d) => s + d.amount, 0), count: mine.length };
  }).filter((c) => c.count > 0);
  const cycleTotal = pickedList.reduce((s, d) => s + d.amount, 0);

  const runPayroll = () => { api.markPaid(pickedList); setPicked(new Set()); force(); };
  const toggleInstall = (id, v) => { api.markInstalled(id, v); force(); };
  const toggleExempt = (id, v) => { api.setExempt(id, v); setPicked(new Set()); force(); };
  const toggleExemptRep = (rep, v) => { api.setExemptByRep(rep, v); setPicked(new Set()); force(); };

  const onSalesFile = (file) => {
    if (!file) return;
    const reader = new FileReader();
    reader.onload = (e) => {
      try { api.importSales(String(e.target.result || "")); setPicked(new Set()); setImportErr(""); setImportResult(null); force(); }
      catch (err) { setImportErr("Could not read that sales CSV. " + (err.message || "")); }
    };
    reader.readAsText(file);
  };
  const onCsvFile = (file) => {
    if (!file) return;
    const reader = new FileReader();
    reader.onload = (e) => {
      try {
        const rows = api.parseCompletions(String(e.target.result || ""));
        if (!rows.length) { setImportErr("No completed jobs found in that file."); setImportResult(null); return; }
        const res = api.applyCompletions(rows);
        setImportResult(res); setImportErr(""); force();
      } catch (err) { setImportErr("Could not read that CSV. " + (err.message || "")); setImportResult(null); }
    };
    reader.readAsText(file);
  };

  const initials = (name) => name.split(" ").map((p) => p[0]).slice(0, 2).join("");

  return (
    <div style={{ maxWidth: "var(--content-max)", margin: "0 auto" }}>
      <div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", marginBottom: 22, flexWrap: "wrap", gap: 16 }}>
        <div>
          <h1 style={{ margin: 0, fontSize: "var(--text-2xl)", fontWeight: 700, letterSpacing: "-0.02em", color: "var(--text-primary)" }}>Payroll &amp; Commissions</h1>
          <p style={{ margin: "4px 0 0", fontSize: "var(--text-sm)", color: "var(--text-muted)" }}>50% on deposit · 50% on completion · from the last 90 days of sales</p>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
          <PR.Button variant="outline" size="md"><Icon name="Download" size={15} />Export Paychecks</PR.Button>
        </div>
      </div>

      {/* KPI heroes */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 16, marginBottom: 22 }}>
        <PR.Card tone="forest" padding="md"><PR.Stat value={fmt(t.depositDue + t.completionDue)} label="Payable Now" tone="forest" align="left" size="md" /></PR.Card>
        <PR.Card padding="md"><PR.Stat value={fmt(t.completionDue)} label="Completion Draws Due" tone="primary" align="left" size="md" /></PR.Card>
        <PR.Card padding="md"><PR.Stat value={fmt(t.heldUninstalled)} label="Held (Not Installed)" align="left" size="md" /></PR.Card>
        <PR.Card padding="md"><PR.Stat value={fmt(t.paid)} label="Paid to Date" align="left" size="md" /></PR.Card>
      </div>

      {/* Tabs */}
      <div style={{ display: "flex", gap: 8, marginBottom: 16 }}>
        {[["run", "Run Payroll"], ["sales", "All Sales (90 days)"], ["history", "Pay Periods"], ["import", "Import Completions"]].map(([k, label]) => (
          <button key={k} onClick={() => setTab(k)} style={{ padding: "8px 16px", borderRadius: "var(--radius-full)", cursor: "pointer", fontFamily: "var(--font-sans)", fontSize: "var(--text-xs)", fontWeight: 600,
            border: `1px solid ${tab === k ? "var(--color-primary)" : "var(--border-default)"}`, background: tab === k ? "var(--color-primary)" : "var(--surface-card)", color: tab === k ? "#fff" : "var(--text-muted)" }}>{label}</button>
        ))}
      </div>

      {tab === "run" ? (
        <div>
        <PR.Card padding="md" style={{ marginBottom: 16, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16, flexWrap: "wrap" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <div style={{ width: 44, height: 44, borderRadius: "var(--radius-lg)", background: "var(--color-primary-soft)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--color-primary-deep)" }}>
              <Icon name="CalendarRange" size={20} />
            </div>
            <div>
              <PR.Eyebrow size="2xs">Pay Period</PR.Eyebrow>
              <div style={{ fontSize: "var(--text-base)", fontWeight: 700, color: "var(--text-primary)" }}>{period ? period.label : "All open periods"}</div>
            </div>
            <button onClick={toggleCompletedOnly} title="Hide deposit draws for jobs that aren't installed yet"
              style={{ display: "inline-flex", alignItems: "center", gap: 7, marginLeft: 8, padding: "8px 14px", borderRadius: "var(--radius-full)", cursor: "pointer", fontFamily: "var(--font-sans)", fontSize: "var(--text-xs)", fontWeight: 600,
                border: `1px solid ${completedOnly ? "var(--color-primary-deep)" : "var(--border-default)"}`,
                background: completedOnly ? "var(--color-primary-deep)" : "var(--surface-card)",
                color: completedOnly ? "#fff" : "var(--text-muted)" }}>
              <Icon name={completedOnly ? "CircleCheck" : "Circle"} size={14} />Completed jobs only
            </button>
          </div>
          <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
            <div style={{ width: 230 }}>
              <PR.Select value={periodId} onChange={(e) => { setPeriodId(e.target.value); clearAll(); }}
                options={[{ value: "", label: "All open periods (" + mineOnly(api.payableDraws("")).length + " due)" }].concat(periods.map((p) => ({ value: p.id, label: p.label + " (" + mineOnly(api.payableDraws(p.id)).length + " due)" })))} />
            </div>
            {canRun && (
            <PR.Button variant={picked.size > 0 && pickedList.length === draws.length ? "deep" : "outline"} onClick={() => (pickedList.length === draws.length ? clearAll() : pickAll())} disabled={draws.length === 0}>
              <Icon name={pickedList.length === draws.length && draws.length > 0 ? "CircleCheck" : "ListChecks"} size={16} />{pickedList.length === draws.length && draws.length > 0 ? "Whole period selected" : "Select whole period"}
            </PR.Button>
            )}
          </div>
        </PR.Card>
        {canRun && byRep.length > 0 && (
        <PR.Card padding="none" style={{ overflow: "hidden", marginBottom: 16 }}>
          <div style={{ padding: "12px 20px", borderBottom: "1px solid var(--border-subtle)" }}>
            <PR.Eyebrow size="2xs">Commissions by Rep · all time</PR.Eyebrow>
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "2fr 1fr 1fr 1fr", gap: 12, padding: "9px 20px", background: "var(--surface-sunken)", borderBottom: "1px solid var(--border-subtle)" }}>
            {["Rep", "Earned", "Paid", "Due"].map((h, i) => <PR.Eyebrow key={i} size="2xs" style={{ textAlign: i ? "right" : "left" }}>{h}</PR.Eyebrow>)}
          </div>
          {byRep.map((r) => (
            <div key={r.rep} style={{ display: "grid", gridTemplateColumns: "2fr 1fr 1fr 1fr", gap: 12, padding: "11px 20px", alignItems: "center", borderBottom: "1px solid var(--border-subtle)" }}>
              <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                <div style={{ width: 30, height: 30, borderRadius: "var(--radius-full)", background: "var(--color-primary-soft)", border: "1px solid var(--color-primary-ring)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--color-primary-deep)", fontWeight: 700, fontSize: 11, flexShrink: 0 }}>{r.rep.split(" ").map((p) => p[0]).slice(0, 2).join("")}</div>
                <span style={{ fontSize: "var(--text-sm)", fontWeight: 600, color: "var(--text-primary)" }}>{r.rep}</span>
              </div>
              <div style={{ textAlign: "right", fontSize: "var(--text-sm)", fontWeight: 700, color: "var(--color-primary-deep)", fontVariantNumeric: "tabular-nums" }}>{fmt(r.earned)}</div>
              <div style={{ textAlign: "right", fontSize: "var(--text-sm)", color: "var(--text-secondary)", fontVariantNumeric: "tabular-nums" }}>{fmt(r.paid)}</div>
              <div style={{ textAlign: "right", fontSize: "var(--text-sm)", fontWeight: 600, color: r.due > 0 ? "var(--status-pending-fg)" : "var(--text-muted)", fontVariantNumeric: "tabular-nums" }}>{fmt(r.due)}</div>
            </div>
          ))}
        </PR.Card>
        )}
        <div style={{ display: "grid", gridTemplateColumns: "1fr 360px", gap: 24, alignItems: "start" }}>
          {/* Payable draws */}
          <PR.Card padding="none" style={{ overflow: "hidden" }}>
            <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "14px 20px", borderBottom: "1px solid var(--border-subtle)" }}>
              <PR.Eyebrow size="2xs">{isRep ? "Your draws due in " : "Due in "}{period ? period.label : "all open periods"} · {draws.length}</PR.Eyebrow>
              <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
                <div style={{ width: 150 }}>
                  <PR.Select value={drawSort.key + ":" + drawSort.dir} onChange={(e) => { const [key, dir] = e.target.value.split(":"); setDrawSort({ key, dir }); }}
                    options={[{ value: "recdate:asc", label: "Sort: Pay date ↑" }, { value: "recdate:desc", label: "Sort: Pay date ↓" }, { value: "kind:asc", label: "Sort: Deposits first" }, { value: "kind:desc", label: "Sort: Completions first" }, { value: "customer:asc", label: "Sort: Customer A–Z" }, { value: "rep:asc", label: "Sort: Rep A–Z" }, { value: "amount:desc", label: "Sort: Amount ↓" }, { value: "amount:asc", label: "Sort: Amount ↑" }]} />
                </div>
                {canRun && <button onClick={pickAll} style={{ border: "none", background: "transparent", cursor: "pointer", color: "var(--color-primary-deep)", fontSize: "var(--text-xs)", fontWeight: 600, fontFamily: "var(--font-sans)" }}>Select all</button>}
                {canRun && <button onClick={clearAll} style={{ border: "none", background: "transparent", cursor: "pointer", color: "var(--text-muted)", fontSize: "var(--text-xs)", fontWeight: 600, fontFamily: "var(--font-sans)" }}>Clear</button>}
              </div>
            </div>
            {draws.length === 0 && <div style={{ padding: 36, textAlign: "center", fontSize: "var(--text-sm)", color: "var(--text-muted)" }}>Nothing to pay — every draw is settled. 🎉</div>}
            {(() => { return sortList(draws, drawSort.key, drawSort.dir, { customer:(d)=>d.customer, rep:(d)=>d.rep, amount:(d)=>d.amount, kind:(d)=>(d.kind==="deposit"?0:1), recdate:(d)=>(d.recPayMs||0) }[drawSort.key]).map((d) => {
              const on = isPicked(d);
              return (
                <React.Fragment key={d.saleId + d.kind}>
                <div onClick={() => canRun && toggle(d)} style={{ display: "flex", alignItems: "center", gap: 12, padding: "12px 20px", borderBottom: "1px solid var(--border-subtle)", cursor: canRun ? "pointer" : "default", background: on ? "var(--color-primary-soft)" : "transparent" }}>
                  {canRun && <span style={{ width: 18, height: 18, borderRadius: 5, flexShrink: 0, border: `2px solid ${on ? "var(--color-primary-deep)" : "var(--border-strong)"}`, background: on ? "var(--color-primary-deep)" : "#fff", display: "flex", alignItems: "center", justifyContent: "center" }}>{on && <Icon name="Check" size={12} color="#fff" />}</span>}
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: "var(--text-sm)", fontWeight: 600, color: "var(--text-primary)" }}>{d.customer}</div>
                    <div style={{ fontSize: "var(--text-2xs)", color: "var(--text-muted)" }}>{d.rep} · {d.saleId} · Sold {d.dateSold || "—"}{d.completedDate ? " · Completed " + d.completedDate : ""} · {fmt(d.value)}</div>
                  </div>
                  <PR.Badge tone={d.kind === "deposit" ? "sky" : "moss"} variant="soft">{d.kind === "deposit" ? "Deposit" : "Completion"}</PR.Badge>
                  {d.kind === "completion" && (
                    <div style={{ width: 120, textAlign: "right" }}>
                      <div style={{ fontSize: "var(--text-2xs)", color: "var(--text-faint)", textTransform: "uppercase", letterSpacing: "0.06em" }}>1st Payment</div>
                      <div style={{ fontSize: "var(--text-xs)", color: "var(--text-secondary)", fontWeight: 600, fontVariantNumeric: "tabular-nums" }}>{fmtD(d.depositAmount)}{d.depositPaid && d.depositPaidDate ? " · " + d.depositPaidDate : d.depositPaid ? " · paid" : " · unpaid"}</div>
                    </div>
                  )}
                  <div style={{ width: 96, textAlign: "right" }}>
                    <div style={{ fontSize: "var(--text-2xs)", color: "var(--text-faint)", textTransform: "uppercase", letterSpacing: "0.06em" }}>{d.recPayDate ? "Rec. Pay" : " "}</div>
                    <div style={{ fontSize: "var(--text-xs)", color: d.recPayDate ? "var(--text-secondary)" : "var(--text-faint)", fontWeight: 600, fontStyle: d.recPayDate ? "normal" : "italic" }}>{d.recPayDate || "payable now"}</div>
                  </div>
                  <div style={{ width: 84, textAlign: "right", fontSize: "var(--text-sm)", fontWeight: 700, color: "var(--text-primary)", fontVariantNumeric: "tabular-nums" }}>{fmtD(d.amount)}</div>
                </div>
                </React.Fragment>
              );
            }); })()}
          </PR.Card>

          {/* Paycheck summary (owner/manager) — or read-only totals (rep) */}
          <div style={{ position: "sticky", top: 24, display: "flex", flexDirection: "column", gap: 16 }}>
            {canRun ? (
            <PR.Card tone="forest" padding="lg">
              <PR.Stat value={fmtD(cycleTotal)} label="This Paycheck Run" tone="forest" align="left" />
              <p style={{ margin: "10px 0 0", fontSize: "var(--text-xs)", color: "rgba(255,255,255,0.5)" }}>{pickedList.length} draw{pickedList.length === 1 ? "" : "s"} · {checks.length} rep{checks.length === 1 ? "" : "s"}</p>
            </PR.Card>
            ) : (
            <PR.Card tone="forest" padding="lg">
              <PR.Stat value={fmtD(draws.reduce((s, d) => s + d.amount, 0))} label="Your Commission Due" tone="forest" align="left" />
              <p style={{ margin: "10px 0 0", fontSize: "var(--text-xs)", color: "rgba(255,255,255,0.5)" }}>{draws.length} draw{draws.length === 1 ? "" : "s"} pending · {fmt(t.paid)} paid to date</p>
            </PR.Card>
            )}

            {canRun && (
            <PR.Card padding="md">
              <PR.Eyebrow size="2xs" style={{ marginBottom: 12 }}>Paychecks</PR.Eyebrow>
              {checks.length === 0 && <p style={{ margin: 0, fontSize: "var(--text-xs)", color: "var(--text-muted)" }}>Select draws to build this cycle's paychecks.</p>}
              <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
                {checks.map((c) => (
                  <div key={c.rep} style={{ display: "flex", alignItems: "center", gap: 10 }}>
                    <div style={{ width: 32, height: 32, borderRadius: "var(--radius-full)", background: "var(--color-primary-soft)", border: "1px solid var(--color-primary-ring)", display: "flex", alignItems: "center", justifyContent: "center", color: "var(--color-primary-deep)", fontWeight: 700, fontSize: 11, flexShrink: 0 }}>{initials(c.rep)}</div>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: "var(--text-sm)", fontWeight: 600, color: "var(--text-primary)" }}>{c.rep}</div>
                      <div style={{ fontSize: "var(--text-2xs)", color: "var(--text-muted)" }}>{c.deposit > 0 ? fmt(c.deposit) + " deposit" : ""}{c.deposit > 0 && c.completion > 0 ? " · " : ""}{c.completion > 0 ? fmt(c.completion) + " completion" : ""}</div>
                    </div>
                    <div style={{ fontSize: "var(--text-sm)", fontWeight: 700, color: "var(--text-primary)", fontVariantNumeric: "tabular-nums" }}>{fmtD(c.deposit + c.completion)}</div>
                  </div>
                ))}
              </div>
            </PR.Card>
            )}

            {canRun && (
            <PR.Button variant="deep" size="lg" disabled={pickedList.length === 0} onClick={runPayroll}>
              <Icon name="Banknote" size={17} />{pickedList.length === 0 ? "Select draws to run" : "Run Payroll · " + fmtD(cycleTotal)}
            </PR.Button>
            )}
            {!canRun && (
            <div style={{ padding: "12px 14px", borderRadius: "var(--radius-lg)", background: "var(--surface-sunken)", border: "1px solid var(--border-subtle)", fontSize: "var(--text-xs)", color: "var(--text-muted)", textAlign: "center" }}>
              You're viewing your own commissions. Payroll is run by an owner or manager.
            </div>
            )}
          </div>
        </div>
        </div>
      ) : tab === "sales" ? (
        /* All sales — mark installed to release completion draws */
        <PR.Card padding="none" style={{ overflow: "hidden" }}>
          <div style={{ display: "grid", gridTemplateColumns: "1.8fr 0.9fr 0.9fr 0.9fr 0.9fr 1.2fr 0.7fr 0.7fr", gap: 12, padding: "12px 20px", background: "var(--surface-sunken)", borderBottom: "1px solid var(--border-subtle)" }}>
            <SortHeader label="Customer" k="customer" sort={salesSort} setSort={setSalesSort} />
            <SortHeader label="Rep" k="rep" sort={salesSort} setSort={setSalesSort} />
            <SortHeader label="Sale Date" k="saleMs" sort={salesSort} setSort={setSalesSort} />
            <SortHeader label="Sale" k="value" sort={salesSort} setSort={setSalesSort} align="right" />
            <SortHeader label="Commission" k="commission" sort={salesSort} setSort={setSalesSort} align="right" />
            <PR.Eyebrow size="2xs">Draws · Paid Date</PR.Eyebrow>
            <SortHeader label="Installed" k="installed" sort={salesSort} setSort={setSalesSort} />
            <SortHeader label="Exempt" k="exempt" sort={salesSort} setSort={setSalesSort} />
          </div>
          {(() => { const monthLbl = (ms) => { const d = new Date(ms); return d.toLocaleString("en-US", { month: "long", year: "numeric", timeZone: "UTC" }); }; const monthTot = {}; sales.forEach((x) => { if (x.saleMs == null) return; const k = monthLbl(x.saleMs); const t = monthTot[k] || (monthTot[k] = { sale: 0, comm: 0, n: 0 }); t.sale += x.value || 0; t.comm += x.exempt ? 0 : (x.commission || 0); t.n += 1; }); let lastMonth = null; return sortList(sales, salesSort.key, salesSort.dir, { customer:(s)=>s.customer, rep:(s)=>s.rep, saleMs:(s)=>s.saleMs, value:(s)=>s.value, commission:(s)=>s.exempt?-1:s.commission, installed:(s)=>s.installed?1:0, exempt:(s)=>s.exempt?1:0 }[salesSort.key]).map((s) => {
            const d1 = s.draw1PaidMs != null ? api.fmtDate(s.draw1PaidMs) : null;
            const d2 = s.draw2PaidMs != null ? api.fmtDate(s.draw2PaidMs) : null;
            const m = salesSort.key === "saleMs" && s.saleMs != null ? monthLbl(s.saleMs) : null;
            const showMonth = m != null && m !== lastMonth;
            lastMonth = m != null ? m : lastMonth;
            return (
            <React.Fragment key={s.id}>
            {showMonth && (
              <div style={{ display: "grid", gridTemplateColumns: "1.8fr 0.9fr 0.9fr 0.9fr 0.9fr 1.2fr 0.7fr 0.7fr", gap: 12, padding: "9px 20px", background: "var(--surface-sunken)", borderBottom: "1px solid var(--border-subtle)", borderTop: "1px solid var(--border-default)", position: "sticky", top: 0, alignItems: "baseline" }}>
                <PR.Eyebrow size="2xs">{m}</PR.Eyebrow>
                <span style={{ fontSize: "var(--text-2xs)", color: "var(--text-faint)" }}>{monthTot[m] ? monthTot[m].n + " sales" : ""}</span>
                <span></span>
                <span style={{ textAlign: "right", fontSize: "var(--text-xs)", fontWeight: 700, color: "var(--text-primary)", fontVariantNumeric: "tabular-nums" }}>{monthTot[m] ? fmt(monthTot[m].sale) : ""}</span>
                <span style={{ textAlign: "right", fontSize: "var(--text-xs)", fontWeight: 700, color: "var(--color-primary-deep)", fontVariantNumeric: "tabular-nums" }}>{monthTot[m] ? fmt(monthTot[m].comm) : ""}</span>
                <span></span><span></span><span></span>
              </div>
            )}
            <div style={{ display: "grid", gridTemplateColumns: "1.8fr 0.9fr 0.9fr 0.9fr 0.9fr 1.2fr 0.7fr 0.7fr", gap: 12, padding: "12px 20px", alignItems: "center", borderBottom: "1px solid var(--border-subtle)", opacity: s.exempt ? 0.55 : 1 }}>
              <div>
                <div style={{ fontSize: "var(--text-sm)", fontWeight: 600, color: "var(--text-primary)" }}>{s.customer}</div>
                <div style={{ fontSize: "var(--text-2xs)", color: "var(--text-muted)" }}>{s.id}</div>
              </div>
              <div style={{ fontSize: "var(--text-sm)", color: "var(--text-secondary)" }}>{s.rep}</div>
              <div style={{ fontSize: "var(--text-xs)", color: "var(--text-secondary)" }}>{s.dateSold}</div>
              <div style={{ textAlign: "right", fontSize: "var(--text-sm)", color: "var(--text-secondary)", fontVariantNumeric: "tabular-nums" }}>{fmt(s.value)}</div>
              <div style={{ textAlign: "right", fontSize: "var(--text-sm)", fontWeight: 700, color: s.exempt ? "var(--text-faint)" : "var(--color-primary-deep)", fontVariantNumeric: "tabular-nums" }}>{s.exempt ? "—" : fmt(s.commission)}</div>
              <div style={{ display: "flex", flexDirection: "column", gap: 2 }}>
                {s.exempt ? <span style={{ fontSize: "var(--text-2xs)", color: "var(--text-faint)" }}>Commission-exempt</span> : (
                  <React.Fragment>
                    <span style={{ fontSize: "var(--text-2xs)", color: s.draw1Paid ? "var(--status-sold-fg)" : "var(--text-muted)" }}>D1 {s.draw1Paid ? "✓ " + (d1 || "paid") : "unpaid"}</span>
                    <span style={{ fontSize: "var(--text-2xs)", color: s.draw2Paid ? "var(--status-sold-fg)" : "var(--text-muted)" }}>D2 {s.draw2Paid ? "✓ " + (d2 || "paid") : (s.installed ? "due" : "held")}</span>
                  </React.Fragment>
                )}
              </div>
              <div style={{ display: "flex", justifyContent: "flex-start" }}>
                <PR.Switch checked={!!s.installed} onChange={(v) => toggleInstall(s.id, v)} disabled={s.exempt || !canRun} />
              </div>
              <div style={{ display: "flex", justifyContent: "flex-start" }}>
                <PR.Switch checked={!!s.exempt} onChange={(v) => toggleExempt(s.id, v)} disabled={!canRun} />
              </div>
            </div>
            </React.Fragment>
            );
          }); })()}
        </PR.Card>
      ) : tab === "history" ? (
        /* Pay Periods — what was paid, when */
        (function () {
          const hist = api.paidHistory().map((g) => ({ ...g, draws: mineOnly(g.draws), total: api.round2(mineOnly(g.draws).reduce((s, d) => s + d.amount, 0)) })).filter((g) => g.draws.length);
          if (!hist.length) return <PR.Card><p style={{ margin: 0, fontSize: "var(--text-sm)", color: "var(--text-muted)", textAlign: "center", padding: 12 }}>No payroll has been run yet. Paid draws will appear here grouped by pay period.</p></PR.Card>;
          return (
            <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
              {hist.map((g) => (
                <PR.Card key={g.period.id} padding="none" style={{ overflow: "hidden" }}>
                  <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "14px 20px", borderBottom: "1px solid var(--border-subtle)" }}>
                    <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                      <Icon name="CalendarCheck" size={18} color="var(--color-primary-deep)" />
                      <span style={{ fontSize: "var(--text-base)", fontWeight: 700, color: "var(--text-primary)" }}>{g.period.label}</span>
                      <PR.Badge tone="green" variant="soft">{g.draws.length} paid</PR.Badge>
                    </div>
                    <div style={{ display: "flex", alignItems: "center", gap: 0 }}>
                    <span style={{ fontSize: "var(--text-lg)", fontWeight: 700, color: "var(--color-primary-deep)", fontVariantNumeric: "tabular-nums" }}>{fmtD(g.total)}</span>
                    {canRun && (
                      <button onClick={() => { api.unpay(g.draws); force(); }} title="Undo this pay period" style={{ marginLeft: 14, display: "inline-flex", alignItems: "center", gap: 5, padding: "6px 12px", borderRadius: "var(--radius-md)", border: "1px solid var(--border-default)", background: "var(--surface-card)", cursor: "pointer", color: "var(--text-secondary)", fontFamily: "var(--font-sans)", fontSize: "var(--text-2xs)", fontWeight: 600 }}>
                        <Icon name="Undo2" size={13} />Undo
                      </button>
                    )}
                    </div>
                  </div>
                  {g.draws.slice().sort((a, b) => a.rep.localeCompare(b.rep) || b.amount - a.amount).map((d, i) => (
                    <div key={d.saleId + d.kind + i} style={{ display: "grid", gridTemplateColumns: "1.8fr 1fr 1fr 1fr 0.9fr", gap: 12, padding: "11px 20px", alignItems: "center", borderBottom: "1px solid var(--border-subtle)" }}>
                      <div>
                        <div style={{ fontSize: "var(--text-sm)", fontWeight: 600, color: "var(--text-primary)" }}>{d.customer}</div>
                        <div style={{ fontSize: "var(--text-2xs)", color: "var(--text-muted)" }}>{d.rep} · {d.saleId}</div>
                      </div>
                      <div><PR.Badge tone={d.kind === "deposit" ? "sky" : "moss"} variant="soft">{d.kind === "deposit" ? "Deposit" : "Completion"}</PR.Badge></div>
                      <div style={{ fontSize: "var(--text-xs)", color: "var(--text-secondary)" }}>Paid {d.paidDate}</div>
                      <div style={{ fontSize: "var(--text-2xs)", color: "var(--text-muted)" }}>{d.kind === "completion" && d.completedDate ? "Completed " + d.completedDate : ""}</div>
                      <div style={{ textAlign: "right", fontSize: "var(--text-sm)", fontWeight: 700, color: "var(--text-primary)", fontVariantNumeric: "tabular-nums" }}>{fmtD(d.amount)}</div>
                    </div>
                  ))}
                </PR.Card>
              ))}
            </div>
          );
        })()
      ) : (
        /* Import completed-jobs CSV */
        <div style={{ display: "grid", gridTemplateColumns: importResult ? "360px 1fr" : "1fr 1fr", gap: 24, alignItems: "start" }}>
          <PR.Card>
            <PR.Eyebrow size="2xs" style={{ marginBottom: 12 }}>Import Sales List</PR.Eyebrow>
            <div
              onDragOver={(e) => { e.preventDefault(); }}
              onDrop={(e) => { e.preventDefault(); onSalesFile(e.dataTransfer.files && e.dataTransfer.files[0]); }}
              onClick={() => salesRef.current && salesRef.current.click()}
              style={{ border: "2px dashed var(--border-default)", borderRadius: "var(--radius-xl)", background: "var(--surface-sunken)", padding: "32px 20px", textAlign: "center", cursor: "pointer" }}>
              <div style={{ width: 48, height: 48, borderRadius: "var(--radius-lg)", background: "var(--color-primary-soft)", display: "inline-flex", alignItems: "center", justifyContent: "center", color: "var(--color-primary-deep)", marginBottom: 12 }}>
                <Icon name="FileSpreadsheet" size={22} />
              </div>
              <div style={{ fontSize: "var(--text-sm)", fontWeight: 600, color: "var(--text-primary)" }}>Drop your sales-list CSV</div>
              <div style={{ fontSize: "var(--text-xs)", color: "var(--text-muted)", marginTop: 4 }}>or click to choose a file</div>
              <input ref={salesRef} type="file" accept=".csv,text/csv" style={{ display: "none" }} onChange={(e) => onSalesFile(e.target.files && e.target.files[0])} />
            </div>
            <p style={{ margin: "14px 0 0", fontSize: "var(--text-2xs)", color: "var(--text-muted)", lineHeight: 1.5 }}>
              Reads the sales export (PO ID · Sales Rep · Customer · Value · Date Sold) and rebuilds the dataset — commission at {Math.round(0.097 * 1000) / 10}%, split into deposit + completion draws. {api.hasUploadedSales() ? "Currently using your uploaded list." : "Currently using the built-in list."}
            </p>
            {api.hasUploadedSales() && <button onClick={() => { api.clearUploadedSales(); force(); }} style={{ marginTop: 8, border: "none", background: "transparent", cursor: "pointer", color: "var(--color-danger)", fontSize: "var(--text-xs)", fontWeight: 600, fontFamily: "var(--font-sans)" }}>Revert to built-in list</button>}
          </PR.Card>
          <PR.Card>
            <PR.Eyebrow size="2xs" style={{ marginBottom: 12 }}>Import Completed Jobs</PR.Eyebrow>
            <div
              onDragOver={(e) => { e.preventDefault(); }}
              onDrop={(e) => { e.preventDefault(); onCsvFile(e.dataTransfer.files && e.dataTransfer.files[0]); }}
              onClick={() => fileRef.current && fileRef.current.click()}
              style={{ border: "2px dashed var(--border-default)", borderRadius: "var(--radius-xl)", background: "var(--surface-sunken)", padding: "32px 20px", textAlign: "center", cursor: "pointer" }}>
              <div style={{ width: 48, height: 48, borderRadius: "var(--radius-lg)", background: "var(--color-primary-soft)", display: "inline-flex", alignItems: "center", justifyContent: "center", color: "var(--color-primary-deep)", marginBottom: 12 }}>
                <Icon name="Upload" size={22} />
              </div>
              <div style={{ fontSize: "var(--text-sm)", fontWeight: 600, color: "var(--text-primary)" }}>Drop your completed-jobs CSV</div>
              <div style={{ fontSize: "var(--text-xs)", color: "var(--text-muted)", marginTop: 4 }}>or click to choose a file</div>
              <input ref={fileRef} type="file" accept=".csv,text/csv" style={{ display: "none" }} onChange={(e) => onCsvFile(e.target.files && e.target.files[0])} />
            </div>
            {importErr && <p style={{ margin: "12px 0 0", fontSize: "var(--text-xs)", color: "var(--color-danger)" }}>{importErr}</p>}
            <p style={{ margin: "14px 0 0", fontSize: "var(--text-2xs)", color: "var(--text-muted)", lineHeight: 1.5 }}>
              Reads the standard export (Name · P.O. · Status · Action Due). Rows marked <strong>Install Complete</strong> are matched to sales by P.O. then customer name; each match releases the job's completion draw, dated to the day it was completed — so it pays in that day's pay period.
            </p>
          </PR.Card>

          {importResult && (
            <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
              <div style={{ display: "flex", gap: 12 }}>
                <PR.Card padding="md" style={{ flex: 1, background: "var(--color-primary-soft)", border: "1px solid var(--color-primary-ring)" }}>
                  <PR.Stat value={importResult.matched.length} label="Completions Applied" tone="primary" align="left" size="md" />
                </PR.Card>
                <PR.Card padding="md" style={{ flex: 1 }}>
                  <PR.Stat value={importResult.unmatched.length} label="Unmatched" align="left" size="md" />
                </PR.Card>
              </div>
              <PR.Card padding="none" style={{ overflow: "hidden" }}>
                <div style={{ display: "grid", gridTemplateColumns: "2fr 1fr 1fr", gap: 12, padding: "11px 18px", background: "var(--surface-sunken)", borderBottom: "1px solid var(--border-subtle)" }}>
                  {["Job", "Completed", "Pays In"].map((h, i) => <PR.Eyebrow key={i} size="2xs">{h}</PR.Eyebrow>)}
                </div>
                {importResult.matched.map((m, i) => (
                  <div key={i} style={{ display: "grid", gridTemplateColumns: "2fr 1fr 1fr", gap: 12, padding: "11px 18px", alignItems: "center", borderBottom: "1px solid var(--border-subtle)" }}>
                    <div>
                      <div style={{ fontSize: "var(--text-sm)", fontWeight: 600, color: "var(--text-primary)" }}>{m.name}</div>
                      <div style={{ fontSize: "var(--text-2xs)", color: "var(--text-muted)" }}>{m.saleId}</div>
                    </div>
                    <div style={{ fontSize: "var(--text-xs)", color: "var(--text-secondary)" }}>{m.dateLabel}</div>
                    <div style={{ fontSize: "var(--text-2xs)" }}><PR.Badge tone="moss" variant="soft">{m.period.label}</PR.Badge></div>
                  </div>
                ))}
                {importResult.matched.length === 0 && <div style={{ padding: 24, textAlign: "center", fontSize: "var(--text-sm)", color: "var(--text-muted)" }}>No rows matched a sale in the system. Check that P.O. or customer names line up.</div>}
              </PR.Card>
              {importResult.unmatched.length > 0 && (
                <PR.Card padding="md">
                  <PR.Eyebrow size="2xs" style={{ marginBottom: 8 }}>Unmatched ({importResult.unmatched.length})</PR.Eyebrow>
                  <div style={{ fontSize: "var(--text-xs)", color: "var(--text-muted)", lineHeight: 1.7 }}>{importResult.unmatched.map((u) => u.name).join(" · ")}</div>
                </PR.Card>
              )}
            </div>
          )}
        </div>
      )}

      <p style={{ margin: "18px 0 0", fontSize: "var(--text-xs)", color: "var(--text-muted)", maxWidth: 640 }}>
        Commission = sale × {Math.round(0.097 * 1000) / 10}% (default rate), split 50% on deposit and 50% on completion. Mark a job <strong>Installed</strong> to release its completion draw, then include it in a payroll run. Changes are saved on this device.
      </p>
    </div>
  );
}

window.Payroll = Payroll;
