// Data Room — read-only detail views over the customer's real Supabase tables.
// Every view shows a clean "No data yet" state until a sync has populated the
// underlying table.
//
//   Trial Balance  →  gl_transactions  (rolled up by month × account)
//   General Ledger →  gl_transactions  (raw line detail, filterable)
//   Sales          →  sales_orders + sales_line_items + customers_master
//   Inventory      →  products
//   Customers      →  customers_master
//   AR / AP Aging  →  gl_transactions filtered by account_mappings.canonical_category

const { useState: useDR_useState, useEffect: useDR_useEffect, useMemo: useDR_useMemo } = React;

// ── Shared shell ───────────────────────────────────────────────────────
function DataRoomShell({ title, subtitle, action, children }) {
  return (
    <div className="pc-page">
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12 }}>
        <div>
          <div style={{ fontSize: 11, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.5 }}>Data room</div>
          <h2 style={{ margin: "2px 0 0", fontSize: 22, fontWeight: 600, letterSpacing: -0.3 }}>{title}</h2>
          {subtitle && <div style={{ fontSize: 13, color: "var(--text-2)", marginTop: 6 }}>{subtitle}</div>}
        </div>
        <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
          {action}
        </div>
      </div>
      {children}
    </div>
  );
}

function EmptyState({ title, hint, onConnect }) {
  return (
    <Card>
      <div style={{ padding: "48px 24px", textAlign: "center" }}>
        <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="var(--text-3)" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" style={{ marginBottom: 12 }}>
          <ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/>
        </svg>
        <div style={{ fontSize: 16, fontWeight: 600, marginBottom: 6 }}>{title}</div>
        <div style={{ fontSize: 13, color: "var(--text-2)", maxWidth: 420, margin: "0 auto 14px", lineHeight: 1.55 }}>{hint}</div>
        {onConnect && <button className="pc-btn-mini" onClick={onConnect}>Go to data sources</button>}
      </div>
    </Card>
  );
}

function CSVDownload({ rows, headers, filename }) {
  const download = () => {
    if (!rows || rows.length === 0) return;
    const escape = (v) => {
      if (v === null || v === undefined) return "";
      const s = String(v).replace(/"/g, '""');
      return /[",\n]/.test(s) ? `"${s}"` : s;
    };
    const lines = [
      headers.map(h => escape(h.label)).join(","),
      ...rows.map(r => headers.map(h => escape(typeof h.value === "function" ? h.value(r) : r[h.value])).join(",")),
    ];
    const blob = new Blob([lines.join("\n")], { type: "text/csv;charset=utf-8" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = filename.endsWith(".csv") ? filename : filename + ".csv";
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    setTimeout(() => URL.revokeObjectURL(url), 200);
  };
  return (
    <button className="pc-btn-mini ghost" onClick={download} disabled={!rows || rows.length === 0} title="Export CSV">
      <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
        <path d="M12 3v14 M5 12l7 7 7-7 M3 21h18" />
      </svg>
      CSV
    </button>
  );
}

// ── companyId resolver (used by every view) ────────────────────────────
function useResolvedCompanyId(scopedCompanyId) {
  const [cid, setCid] = useDR_useState(scopedCompanyId || null);
  useDR_useEffect(() => {
    if (scopedCompanyId) { setCid(scopedCompanyId); return; }
    const db = window.supabaseClient;
    if (!db) return;
    (async () => {
      const { data: { session } } = await db.auth.getSession();
      if (!session) return;
      const { data: m } = await db.from("company_users").select("company_id").eq("user_id", session.user.id).in("status", ["Active", "Pending"]).maybeSingle();
      if (m?.company_id) setCid(m.company_id);
    })();
  }, [scopedCompanyId]);
  return cid;
}

// ── Sortable column header ─────────────────────────────────────────────
function SortHeader({ label, sortKey, current, setCurrent, align = "left" }) {
  const isActive = current.key === sortKey;
  const dir = isActive ? current.dir : null;
  return (
    <th style={{ textAlign: align, cursor: "pointer", userSelect: "none" }}
        onClick={() => setCurrent({ key: sortKey, dir: isActive ? (dir === "asc" ? "desc" : "asc") : "asc" })}>
      <span style={{ display: "inline-flex", alignItems: "center", gap: 4 }}>
        {label}
        <span style={{ fontSize: 9, color: isActive ? "var(--accent)" : "var(--text-4)" }}>
          {dir === "asc" ? "▲" : dir === "desc" ? "▼" : "↕"}
        </span>
      </span>
    </th>
  );
}

function applySort(rows, sort) {
  if (!sort.key) return rows;
  const k = sort.key, dir = sort.dir === "desc" ? -1 : 1;
  return [...rows].sort((a, b) => {
    const av = a[k], bv = b[k];
    if (av === bv) return 0;
    if (av == null) return 1;
    if (bv == null) return -1;
    if (typeof av === "number" && typeof bv === "number") return (av - bv) * dir;
    return String(av).localeCompare(String(bv)) * dir;
  });
}

// ── Period filter dropdown wrapper (reads the global period) ──────────
function PeriodFilterBadge({ resolved }) {
  if (!resolved) return null;
  return (
    <div style={{
      display: "inline-flex", alignItems: "center", gap: 6,
      padding: "4px 10px", background: "var(--bg-elev-1)", border: "1px solid var(--border)",
      borderRadius: 6, fontSize: 11.5, color: "var(--text-2)",
    }}>
      <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
        <rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/>
      </svg>
      {resolved.startDate} → {resolved.endDate}
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────
// 1. TRIAL BALANCE
// ────────────────────────────────────────────────────────────────────────
function DataTrialBalancePage({ scopedCompanyId, periodResolved, setPage }) {
  const companyId = useResolvedCompanyId(scopedCompanyId);
  const [loading, setLoading] = useDR_useState(true);
  const [txns, setTxns] = useDR_useState([]);
  const [mappings, setMappings] = useDR_useState([]);
  const [sort, setSort] = useDR_useState({ key: "account_code", dir: "asc" });
  const [search, setSearch] = useDR_useState("");

  useDR_useEffect(() => {
    if (!companyId || !periodResolved) { setLoading(false); return; }
    setLoading(true);
    const db = window.supabaseClient;
    if (!db) { setLoading(false); return; }
    (async () => {
      const [{ data: rawTxns }, { data: rawMappings }] = await Promise.all([
        db.from("gl_transactions")
          .select("account_code, account_name, amount, posted_date")
          .eq("company_id", companyId)
          .gte("posted_date", periodResolved.startDate)
          .lte("posted_date", periodResolved.endDate)
          .order("posted_date", { ascending: true }),
        db.from("account_mappings")
          .select("account_code, account_name, canonical_category, subcategory")
          .eq("company_id", companyId),
      ]);
      setTxns(rawTxns || []);
      setMappings(rawMappings || []);
      setLoading(false);
    })();
  }, [companyId, periodResolved?.startDate, periodResolved?.endDate]);

  // Build TB rollup: one row per account, one column per month in the period.
  const months = periodResolved?.months || [];
  const tb = useDR_useMemo(() => {
    const byCode = new Map();
    const mapMap = new Map();
    mappings.forEach(m => mapMap.set(m.account_code, m));
    txns.forEach(tx => {
      const code = tx.account_code || "(unmapped)";
      if (!byCode.has(code)) {
        const m = mapMap.get(code) || {};
        byCode.set(code, {
          account_code: code,
          account_name: tx.account_name || m.account_name || "",
          canonical_category: m.canonical_category || "",
          subcategory: m.subcategory || "",
          monthly: months.map(() => 0),
          debits: 0, credits: 0, balance: 0,
        });
      }
      const row = byCode.get(code);
      const d = new Date(tx.posted_date);
      const mIdx = months.findIndex(mm => mm.year === d.getFullYear() && mm.month1 === d.getMonth() + 1);
      const amt = parseFloat(tx.amount) || 0;
      if (mIdx >= 0) row.monthly[mIdx] += amt;
      if (amt >= 0) row.debits += amt; else row.credits += -amt;
      row.balance += amt;
    });
    return Array.from(byCode.values());
  }, [txns, mappings, months]);

  const filtered = useDR_useMemo(() => {
    if (!search) return tb;
    const q = search.toLowerCase();
    return tb.filter(r => (r.account_code || "").toLowerCase().includes(q)
      || (r.account_name || "").toLowerCase().includes(q)
      || (r.canonical_category || "").toLowerCase().includes(q));
  }, [tb, search]);

  const sorted = useDR_useMemo(() => applySort(filtered, sort), [filtered, sort]);

  const totals = useDR_useMemo(() => ({
    debits: sorted.reduce((s, r) => s + r.debits, 0),
    credits: sorted.reduce((s, r) => s + r.credits, 0),
    balance: sorted.reduce((s, r) => s + r.balance, 0),
    monthly: months.map((_, i) => sorted.reduce((s, r) => s + r.monthly[i], 0)),
  }), [sorted, months]);

  const csvHeaders = [
    { label: "Account code", value: "account_code" },
    { label: "Account name", value: "account_name" },
    { label: "Category",     value: "canonical_category" },
    ...months.map((m, i) => ({ label: m.label, value: r => r.monthly[i] })),
    { label: "Debits",  value: "debits" },
    { label: "Credits", value: "credits" },
    { label: "Balance", value: "balance" },
  ];

  return (
    <DataRoomShell
      title="Trial Balance"
      subtitle="Every GL account, rolled up by month, with debit / credit / net balance."
      action={
        <>
          <PeriodFilterBadge resolved={periodResolved} />
          <input className="pc-period-select" placeholder="Search account…" value={search}
                 onChange={e => setSearch(e.target.value)} style={{ minWidth: 180 }} />
          <CSVDownload rows={sorted} headers={csvHeaders} filename={`trial_balance_${periodResolved?.startDate || ""}_${periodResolved?.endDate || ""}`} />
        </>
      }
    >
      {loading ? (
        <Card><div style={{ padding: 32, textAlign: "center", color: "var(--text-3)" }}>Loading…</div></Card>
      ) : tb.length === 0 ? (
        <EmptyState
          title="No data yet"
          hint="Once your accounting software syncs, your trial balance will appear here automatically — by month, by account."
          onConnect={setPage ? () => setPage("settings_config") : null}
        />
      ) : (
        <Card padding={0}>
          <div style={{ overflowX: "auto" }}>
            <table className="pc-table compact">
              <thead>
                <tr>
                  <SortHeader label="Code"     sortKey="account_code"       current={sort} setCurrent={setSort} />
                  <SortHeader label="Account"  sortKey="account_name"       current={sort} setCurrent={setSort} />
                  <SortHeader label="Category" sortKey="canonical_category" current={sort} setCurrent={setSort} />
                  {months.map(m => <th key={m.label} style={{ textAlign: "right" }}>{m.label}</th>)}
                  <SortHeader label="Debits"  sortKey="debits"  current={sort} setCurrent={setSort} align="right" />
                  <SortHeader label="Credits" sortKey="credits" current={sort} setCurrent={setSort} align="right" />
                  <SortHeader label="Balance" sortKey="balance" current={sort} setCurrent={setSort} align="right" />
                </tr>
              </thead>
              <tbody>
                {sorted.map((r, i) => (
                  <tr key={r.account_code + i}>
                    <td style={{ paddingLeft: 14, fontFamily: "ui-monospace, monospace", fontSize: 11 }}>{r.account_code}</td>
                    <td>{r.account_name || <span style={{ color: "var(--text-4)" }}>—</span>}</td>
                    <td style={{ fontSize: 11.5, color: "var(--text-2)" }}>{r.canonical_category || <span style={{ color: "var(--text-4)" }}>—</span>}</td>
                    {r.monthly.map((v, j) => (
                      <td key={j} style={{ textAlign: "right", fontFamily: "ui-monospace, monospace", fontSize: 11.5,
                                            color: v === 0 ? "var(--text-4)" : "var(--text-2)" }}>
                        {v === 0 ? "—" : fmtUSD(v, { compact: true })}
                      </td>
                    ))}
                    <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace", fontSize: 11.5 }}>{fmtUSD(r.debits, { compact: true })}</td>
                    <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace", fontSize: 11.5 }}>{fmtUSD(r.credits, { compact: true })}</td>
                    <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace", fontSize: 11.5,
                                  color: r.balance >= 0 ? "var(--text-2)" : "var(--danger)" }}>
                      {fmtUSD(r.balance, { compact: true })}
                    </td>
                  </tr>
                ))}
              </tbody>
              <tfoot>
                <tr style={{ fontWeight: 600 }}>
                  <td style={{ paddingLeft: 14 }} colSpan={3}>Totals</td>
                  {totals.monthly.map((v, j) => (
                    <td key={j} style={{ textAlign: "right", fontFamily: "ui-monospace, monospace" }}>{fmtUSD(v, { compact: true })}</td>
                  ))}
                  <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace" }}>{fmtUSD(totals.debits, { compact: true })}</td>
                  <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace" }}>{fmtUSD(totals.credits, { compact: true })}</td>
                  <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace" }}>{fmtUSD(totals.balance, { compact: true })}</td>
                </tr>
              </tfoot>
            </table>
          </div>
        </Card>
      )}
    </DataRoomShell>
  );
}

// ────────────────────────────────────────────────────────────────────────
// 2. GENERAL LEDGER
// ────────────────────────────────────────────────────────────────────────
function DataGeneralLedgerPage({ scopedCompanyId, periodResolved, setPage }) {
  const companyId = useResolvedCompanyId(scopedCompanyId);
  const [loading, setLoading] = useDR_useState(true);
  const [rows, setRows] = useDR_useState([]);
  const [accountFilter, setAccountFilter] = useDR_useState("");
  const [search, setSearch] = useDR_useState("");
  const [sort, setSort] = useDR_useState({ key: "posted_date", dir: "desc" });

  useDR_useEffect(() => {
    if (!companyId || !periodResolved) { setLoading(false); return; }
    setLoading(true);
    const db = window.supabaseClient;
    if (!db) { setLoading(false); return; }
    (async () => {
      const { data } = await db.from("gl_transactions")
        .select("id, posted_date, account_code, account_name, amount, memo, reference, source_system, created_at")
        .eq("company_id", companyId)
        .gte("posted_date", periodResolved.startDate)
        .lte("posted_date", periodResolved.endDate)
        .order("posted_date", { ascending: false })
        .limit(5000);
      setRows(data || []);
      setLoading(false);
    })();
  }, [companyId, periodResolved?.startDate, periodResolved?.endDate]);

  const accountOptions = useDR_useMemo(() => {
    const m = new Map();
    rows.forEach(r => { if (r.account_code) m.set(r.account_code, r.account_name || r.account_code); });
    return Array.from(m.entries()).sort();
  }, [rows]);

  const filtered = useDR_useMemo(() => {
    const q = search.toLowerCase();
    return rows.filter(r => {
      if (accountFilter && r.account_code !== accountFilter) return false;
      if (!q) return true;
      return (r.memo || "").toLowerCase().includes(q)
        || (r.reference || "").toLowerCase().includes(q)
        || (r.account_name || "").toLowerCase().includes(q)
        || (r.account_code || "").toLowerCase().includes(q);
    });
  }, [rows, accountFilter, search]);

  const sorted = useDR_useMemo(() => applySort(filtered, sort), [filtered, sort]);

  const csvHeaders = [
    { label: "Date",         value: "posted_date" },
    { label: "Account code", value: "account_code" },
    { label: "Account name", value: "account_name" },
    { label: "Memo",         value: "memo" },
    { label: "Reference",    value: "reference" },
    { label: "Amount",       value: "amount" },
    { label: "Source",       value: "source_system" },
  ];

  return (
    <DataRoomShell
      title="General Ledger"
      subtitle="Every transaction in the period, with full memo and reference detail."
      action={
        <>
          <PeriodFilterBadge resolved={periodResolved} />
          <select className="pc-period-select" value={accountFilter} onChange={e => setAccountFilter(e.target.value)} style={{ minWidth: 160 }}>
            <option value="">All accounts</option>
            {accountOptions.map(([code, name]) => <option key={code} value={code}>{code} · {name}</option>)}
          </select>
          <input className="pc-period-select" placeholder="Search memo…" value={search} onChange={e => setSearch(e.target.value)} style={{ minWidth: 180 }} />
          <CSVDownload rows={sorted} headers={csvHeaders} filename={`general_ledger_${periodResolved?.startDate || ""}_${periodResolved?.endDate || ""}`} />
        </>
      }
    >
      {loading ? (
        <Card><div style={{ padding: 32, textAlign: "center", color: "var(--text-3)" }}>Loading…</div></Card>
      ) : rows.length === 0 ? (
        <EmptyState title="No data yet" hint="Transactions will appear here as soon as your accounting software starts syncing." onConnect={setPage ? () => setPage("settings_config") : null} />
      ) : (
        <Card padding={0}>
          <div style={{ fontSize: 11, color: "var(--text-3)", padding: "10px 14px", borderBottom: "1px solid var(--border)" }}>
            {sorted.length.toLocaleString()} of {rows.length.toLocaleString()} transactions{rows.length === 5000 ? " (showing first 5,000)" : ""}
          </div>
          <table className="pc-table compact">
            <thead>
              <tr>
                <SortHeader label="Date"      sortKey="posted_date"  current={sort} setCurrent={setSort} />
                <SortHeader label="Account"   sortKey="account_code" current={sort} setCurrent={setSort} />
                <th>Memo</th>
                <SortHeader label="Reference" sortKey="reference" current={sort} setCurrent={setSort} />
                <SortHeader label="Amount"    sortKey="amount"    current={sort} setCurrent={setSort} align="right" />
                <th>Source</th>
              </tr>
            </thead>
            <tbody>
              {sorted.slice(0, 1000).map(r => (
                <tr key={r.id}>
                  <td style={{ paddingLeft: 14, fontFamily: "ui-monospace, monospace", fontSize: 11 }}>{r.posted_date}</td>
                  <td>
                    <div style={{ fontFamily: "ui-monospace, monospace", fontSize: 11, color: "var(--text-3)" }}>{r.account_code}</div>
                    <div style={{ fontSize: 12 }}>{r.account_name}</div>
                  </td>
                  <td style={{ fontSize: 12, color: "var(--text-2)", maxWidth: 320, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{r.memo || ""}</td>
                  <td style={{ fontFamily: "ui-monospace, monospace", fontSize: 11, color: "var(--text-3)" }}>{r.reference || ""}</td>
                  <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace", fontSize: 11.5,
                                color: parseFloat(r.amount) >= 0 ? "var(--text-2)" : "var(--danger)" }}>
                    {fmtUSD(parseFloat(r.amount), { compact: true })}
                  </td>
                  <td style={{ fontSize: 11, color: "var(--text-3)" }}>{r.source_system || ""}</td>
                </tr>
              ))}
            </tbody>
          </table>
          {sorted.length > 1000 && (
            <div style={{ padding: 12, textAlign: "center", fontSize: 12, color: "var(--text-3)", borderTop: "1px solid var(--border)" }}>
              Showing first 1,000 of {sorted.length.toLocaleString()} rows. Export to CSV for the full list.
            </div>
          )}
        </Card>
      )}
    </DataRoomShell>
  );
}

// ────────────────────────────────────────────────────────────────────────
// 3. SALES
// ────────────────────────────────────────────────────────────────────────
function DataSalesPage({ scopedCompanyId, periodResolved, setPage }) {
  const companyId = useResolvedCompanyId(scopedCompanyId);
  const [loading, setLoading] = useDR_useState(true);
  const [orders, setOrders] = useDR_useState([]);
  const [lines,  setLines]  = useDR_useState([]);
  const [tab, setTab] = useDR_useState("orders");
  const [sort, setSort] = useDR_useState({ key: "order_date", dir: "desc" });
  const [search, setSearch] = useDR_useState("");

  useDR_useEffect(() => {
    if (!companyId || !periodResolved) { setLoading(false); return; }
    setLoading(true);
    const db = window.supabaseClient;
    if (!db) { setLoading(false); return; }
    (async () => {
      const [{ data: rawOrders }, { data: rawLines }] = await Promise.all([
        db.from("sales_orders")
          .select("id, order_number, order_date, customer_name, status, channel, currency, subtotal_cents, discount_cents, tax_cents, total_cents, cogs_cents, gross_profit_cents")
          .eq("company_id", companyId)
          .gte("order_date", periodResolved.startDate)
          .lte("order_date", periodResolved.endDate)
          .order("order_date", { ascending: false })
          .limit(5000),
        db.from("sales_line_items")
          .select("id, order_id, sku, product_name, category, quantity, unit_price_cents, unit_cost_cents, line_total_cents, line_cost_cents, line_gross_profit_cents, gross_margin_pct, order_date")
          .eq("company_id", companyId)
          .gte("order_date", periodResolved.startDate)
          .lte("order_date", periodResolved.endDate)
          .order("order_date", { ascending: false })
          .limit(10000),
      ]);
      setOrders(rawOrders || []);
      setLines(rawLines || []);
      setLoading(false);
    })();
  }, [companyId, periodResolved?.startDate, periodResolved?.endDate]);

  const orderRows = useDR_useMemo(() => orders.map(o => ({
    ...o,
    total: (o.total_cents || 0) / 100,
    subtotal: (o.subtotal_cents || 0) / 100,
    discount: (o.discount_cents || 0) / 100,
    cogs:  (o.cogs_cents || 0) / 100,
    gross_profit: (o.gross_profit_cents || 0) / 100,
  })), [orders]);

  const lineRows = useDR_useMemo(() => lines.map(l => ({
    ...l,
    unit_price: (l.unit_price_cents || 0) / 100,
    unit_cost:  (l.unit_cost_cents || 0) / 100,
    line_total: (l.line_total_cents || 0) / 100,
    line_cost:  (l.line_cost_cents || 0) / 100,
    line_gross_profit: (l.line_gross_profit_cents || 0) / 100,
  })), [lines]);

  const filterRows = (rows) => {
    if (!search) return rows;
    const q = search.toLowerCase();
    return rows.filter(r =>
      (r.order_number || "").toLowerCase().includes(q)
      || (r.customer_name || "").toLowerCase().includes(q)
      || (r.product_name || "").toLowerCase().includes(q)
      || (r.sku || "").toLowerCase().includes(q)
      || (r.channel || "").toLowerCase().includes(q));
  };

  const sortedOrders = useDR_useMemo(() => applySort(filterRows(orderRows), sort), [orderRows, search, sort]);
  const sortedLines  = useDR_useMemo(() => applySort(filterRows(lineRows),  sort), [lineRows,  search, sort]);

  const orderCsv = [
    { label: "Order #", value: "order_number" }, { label: "Date", value: "order_date" },
    { label: "Customer", value: "customer_name" }, { label: "Channel", value: "channel" },
    { label: "Status", value: "status" }, { label: "Subtotal", value: "subtotal" },
    { label: "Discount", value: "discount" }, { label: "Total", value: "total" },
    { label: "COGS", value: "cogs" }, { label: "Gross profit", value: "gross_profit" },
  ];
  const lineCsv = [
    { label: "Date", value: "order_date" }, { label: "SKU", value: "sku" },
    { label: "Product", value: "product_name" }, { label: "Category", value: "category" },
    { label: "Qty", value: "quantity" }, { label: "Unit price", value: "unit_price" },
    { label: "Unit cost", value: "unit_cost" }, { label: "Line total", value: "line_total" },
    { label: "Line GP",  value: "line_gross_profit" }, { label: "GM%", value: "gross_margin_pct" },
  ];

  const noData = orderRows.length === 0 && lineRows.length === 0;

  return (
    <DataRoomShell
      title="Sales"
      subtitle="Orders and line items from your connected order system."
      action={
        <>
          <PeriodFilterBadge resolved={periodResolved} />
          <input className="pc-period-select" placeholder="Search…" value={search} onChange={e => setSearch(e.target.value)} style={{ minWidth: 180 }} />
          {tab === "orders"
            ? <CSVDownload rows={sortedOrders} headers={orderCsv} filename={`sales_orders_${periodResolved?.startDate || ""}_${periodResolved?.endDate || ""}`} />
            : <CSVDownload rows={sortedLines}  headers={lineCsv}  filename={`sales_lines_${periodResolved?.startDate || ""}_${periodResolved?.endDate || ""}`} />}
        </>
      }
    >
      {loading ? (
        <Card><div style={{ padding: 32, textAlign: "center", color: "var(--text-3)" }}>Loading…</div></Card>
      ) : noData ? (
        <EmptyState title="No data yet" hint="Connect your order system (Shopify, Stripe, etc.) — your orders and SKU detail will sync here." onConnect={setPage ? () => setPage("settings_config") : null} />
      ) : (
        <>
          <div className="pc-section-tabs">
            <button className={tab === "orders" ? "active" : ""} onClick={() => setTab("orders")}>Orders ({orderRows.length.toLocaleString()})</button>
            <button className={tab === "lines"  ? "active" : ""} onClick={() => setTab("lines")}>Line items ({lineRows.length.toLocaleString()})</button>
          </div>

          {tab === "orders" && (
            <Card padding={0}>
              <table className="pc-table compact">
                <thead>
                  <tr>
                    <SortHeader label="Date"     sortKey="order_date"    current={sort} setCurrent={setSort} />
                    <SortHeader label="Order #"  sortKey="order_number"  current={sort} setCurrent={setSort} />
                    <SortHeader label="Customer" sortKey="customer_name" current={sort} setCurrent={setSort} />
                    <SortHeader label="Channel"  sortKey="channel"       current={sort} setCurrent={setSort} />
                    <SortHeader label="Status"   sortKey="status"        current={sort} setCurrent={setSort} />
                    <SortHeader label="Total"    sortKey="total"         current={sort} setCurrent={setSort} align="right" />
                    <SortHeader label="GP"       sortKey="gross_profit"  current={sort} setCurrent={setSort} align="right" />
                  </tr>
                </thead>
                <tbody>
                  {sortedOrders.slice(0, 1000).map(r => (
                    <tr key={r.id}>
                      <td style={{ paddingLeft: 14, fontFamily: "ui-monospace, monospace", fontSize: 11 }}>{r.order_date}</td>
                      <td style={{ fontFamily: "ui-monospace, monospace", fontSize: 11.5 }}>{r.order_number || "—"}</td>
                      <td>{r.customer_name || <span style={{ color: "var(--text-4)" }}>—</span>}</td>
                      <td style={{ fontSize: 11.5, color: "var(--text-2)" }}>{r.channel || "—"}</td>
                      <td><span className="pc-chip">{r.status || "—"}</span></td>
                      <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace" }}>{fmtUSD(r.total, { compact: true })}</td>
                      <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace", color: r.gross_profit >= 0 ? "var(--text-2)" : "var(--danger)" }}>{fmtUSD(r.gross_profit, { compact: true })}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </Card>
          )}

          {tab === "lines" && (
            <Card padding={0}>
              <table className="pc-table compact">
                <thead>
                  <tr>
                    <SortHeader label="Date"     sortKey="order_date"   current={sort} setCurrent={setSort} />
                    <SortHeader label="SKU"      sortKey="sku"          current={sort} setCurrent={setSort} />
                    <SortHeader label="Product"  sortKey="product_name" current={sort} setCurrent={setSort} />
                    <SortHeader label="Category" sortKey="category"     current={sort} setCurrent={setSort} />
                    <SortHeader label="Qty"      sortKey="quantity"     current={sort} setCurrent={setSort} align="right" />
                    <SortHeader label="Unit price" sortKey="unit_price" current={sort} setCurrent={setSort} align="right" />
                    <SortHeader label="Line total" sortKey="line_total" current={sort} setCurrent={setSort} align="right" />
                    <SortHeader label="GM%"        sortKey="gross_margin_pct" current={sort} setCurrent={setSort} align="right" />
                  </tr>
                </thead>
                <tbody>
                  {sortedLines.slice(0, 1000).map(r => (
                    <tr key={r.id}>
                      <td style={{ paddingLeft: 14, fontFamily: "ui-monospace, monospace", fontSize: 11 }}>{r.order_date}</td>
                      <td style={{ fontFamily: "ui-monospace, monospace", fontSize: 11.5 }}>{r.sku || "—"}</td>
                      <td>{r.product_name || <span style={{ color: "var(--text-4)" }}>—</span>}</td>
                      <td style={{ fontSize: 11.5, color: "var(--text-2)" }}>{r.category || "—"}</td>
                      <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace" }}>{r.quantity}</td>
                      <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace" }}>{fmtUSD(r.unit_price)}</td>
                      <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace" }}>{fmtUSD(r.line_total, { compact: true })}</td>
                      <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace",
                                    color: r.gross_margin_pct >= 0 ? "var(--text-2)" : "var(--danger)" }}>
                        {r.gross_margin_pct != null ? Number(r.gross_margin_pct).toFixed(1) + "%" : "—"}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </Card>
          )}
        </>
      )}
    </DataRoomShell>
  );
}

// ────────────────────────────────────────────────────────────────────────
// 4. INVENTORY / PRODUCTS
// ────────────────────────────────────────────────────────────────────────
function DataInventoryPage({ scopedCompanyId, periodResolved, setPage }) {
  const companyId = useResolvedCompanyId(scopedCompanyId);
  const [loading, setLoading] = useDR_useState(true);
  const [rows, setRows] = useDR_useState([]);
  const [sort, setSort] = useDR_useState({ key: "name", dir: "asc" });
  const [search, setSearch] = useDR_useState("");

  useDR_useEffect(() => {
    if (!companyId) { setLoading(false); return; }
    setLoading(true);
    const db = window.supabaseClient;
    if (!db) { setLoading(false); return; }
    (async () => {
      const { data } = await db.from("products")
        .select("id, sku, name, category, sub_category, unit_cost_cents, unit_price_cents, is_active, source_system")
        .eq("company_id", companyId)
        .order("name", { ascending: true });
      const mapped = (data || []).map(p => ({
        ...p,
        unit_cost:  (p.unit_cost_cents  || 0) / 100,
        unit_price: (p.unit_price_cents || 0) / 100,
        margin: p.unit_price_cents ? Math.round(((p.unit_price_cents - p.unit_cost_cents) / p.unit_price_cents) * 1000) / 10 : null,
      }));
      setRows(mapped);
      setLoading(false);
    })();
  }, [companyId]);

  const filtered = useDR_useMemo(() => {
    if (!search) return rows;
    const q = search.toLowerCase();
    return rows.filter(r => (r.sku || "").toLowerCase().includes(q)
      || (r.name || "").toLowerCase().includes(q)
      || (r.category || "").toLowerCase().includes(q));
  }, [rows, search]);

  const sorted = useDR_useMemo(() => applySort(filtered, sort), [filtered, sort]);

  const csvHeaders = [
    { label: "SKU", value: "sku" }, { label: "Name", value: "name" },
    { label: "Category", value: "category" }, { label: "Subcategory", value: "sub_category" },
    { label: "Unit cost", value: "unit_cost" }, { label: "Unit price", value: "unit_price" },
    { label: "Margin %",  value: "margin" }, { label: "Active", value: "is_active" },
    { label: "Source", value: "source_system" },
  ];

  return (
    <DataRoomShell
      title="Inventory / Products"
      subtitle="Product master — every SKU with cost, price, and margin."
      action={
        <>
          <input className="pc-period-select" placeholder="Search…" value={search} onChange={e => setSearch(e.target.value)} style={{ minWidth: 180 }} />
          <CSVDownload rows={sorted} headers={csvHeaders} filename="products" />
        </>
      }
    >
      {loading ? (
        <Card><div style={{ padding: 32, textAlign: "center", color: "var(--text-3)" }}>Loading…</div></Card>
      ) : rows.length === 0 ? (
        <EmptyState title="No products yet" hint="Sync Shopify, your POS, or upload a product spreadsheet to populate this view." onConnect={setPage ? () => setPage("settings_config") : null} />
      ) : (
        <Card padding={0}>
          <table className="pc-table compact">
            <thead>
              <tr>
                <SortHeader label="SKU"        sortKey="sku"           current={sort} setCurrent={setSort} />
                <SortHeader label="Product"    sortKey="name"          current={sort} setCurrent={setSort} />
                <SortHeader label="Category"   sortKey="category"      current={sort} setCurrent={setSort} />
                <SortHeader label="Unit cost"  sortKey="unit_cost"     current={sort} setCurrent={setSort} align="right" />
                <SortHeader label="Unit price" sortKey="unit_price"    current={sort} setCurrent={setSort} align="right" />
                <SortHeader label="Margin %"   sortKey="margin"        current={sort} setCurrent={setSort} align="right" />
                <th>Active</th><th>Source</th>
              </tr>
            </thead>
            <tbody>
              {sorted.map(r => (
                <tr key={r.id}>
                  <td style={{ paddingLeft: 14, fontFamily: "ui-monospace, monospace", fontSize: 11 }}>{r.sku || "—"}</td>
                  <td>{r.name}</td>
                  <td style={{ fontSize: 11.5, color: "var(--text-2)" }}>{r.category || "—"}</td>
                  <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace" }}>{fmtUSD(r.unit_cost)}</td>
                  <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace" }}>{fmtUSD(r.unit_price)}</td>
                  <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace",
                                color: r.margin == null ? "var(--text-4)" : r.margin >= 0 ? "var(--text-2)" : "var(--danger)" }}>
                    {r.margin == null ? "—" : r.margin.toFixed(1) + "%"}
                  </td>
                  <td style={{ fontSize: 11 }}>{r.is_active ? "Yes" : "No"}</td>
                  <td style={{ fontSize: 11, color: "var(--text-3)" }}>{r.source_system || "—"}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </Card>
      )}
    </DataRoomShell>
  );
}

// ────────────────────────────────────────────────────────────────────────
// 5. CUSTOMERS
// ────────────────────────────────────────────────────────────────────────
function DataCustomersPage({ scopedCompanyId, periodResolved, setPage }) {
  const companyId = useResolvedCompanyId(scopedCompanyId);
  const [loading, setLoading] = useDR_useState(true);
  const [rows, setRows] = useDR_useState([]);
  const [search, setSearch] = useDR_useState("");
  const [sort, setSort] = useDR_useState({ key: "lifetime_value", dir: "desc" });

  useDR_useEffect(() => {
    if (!companyId) { setLoading(false); return; }
    setLoading(true);
    const db = window.supabaseClient;
    if (!db) { setLoading(false); return; }
    (async () => {
      const { data } = await db.from("customers_master")
        .select("id, name, email, segment, acquisition_channel, acquisition_date, lifetime_value_cents, order_count, last_order_date, source_system")
        .eq("company_id", companyId)
        .order("lifetime_value_cents", { ascending: false });
      const mapped = (data || []).map(c => ({ ...c, lifetime_value: (c.lifetime_value_cents || 0) / 100 }));
      setRows(mapped);
      setLoading(false);
    })();
  }, [companyId]);

  const filtered = useDR_useMemo(() => {
    if (!search) return rows;
    const q = search.toLowerCase();
    return rows.filter(r => (r.name || "").toLowerCase().includes(q)
      || (r.email || "").toLowerCase().includes(q)
      || (r.segment || "").toLowerCase().includes(q));
  }, [rows, search]);

  const sorted = useDR_useMemo(() => applySort(filtered, sort), [filtered, sort]);

  const csvHeaders = [
    { label: "Name", value: "name" }, { label: "Email", value: "email" },
    { label: "Segment", value: "segment" }, { label: "Channel", value: "acquisition_channel" },
    { label: "Acquired", value: "acquisition_date" }, { label: "Orders", value: "order_count" },
    { label: "Lifetime value", value: "lifetime_value" }, { label: "Last order", value: "last_order_date" },
    { label: "Source", value: "source_system" },
  ];

  return (
    <DataRoomShell
      title="Customers"
      subtitle="Customer master — lifetime value, order count, acquisition channel."
      action={
        <>
          <input className="pc-period-select" placeholder="Search…" value={search} onChange={e => setSearch(e.target.value)} style={{ minWidth: 180 }} />
          <CSVDownload rows={sorted} headers={csvHeaders} filename="customers" />
        </>
      }
    >
      {loading ? (
        <Card><div style={{ padding: 32, textAlign: "center", color: "var(--text-3)" }}>Loading…</div></Card>
      ) : rows.length === 0 ? (
        <EmptyState title="No customers yet" hint="Customer records will sync from your order system or CRM once connected." onConnect={setPage ? () => setPage("settings_config") : null} />
      ) : (
        <Card padding={0}>
          <table className="pc-table compact">
            <thead>
              <tr>
                <SortHeader label="Name"     sortKey="name"            current={sort} setCurrent={setSort} />
                <SortHeader label="Email"    sortKey="email"           current={sort} setCurrent={setSort} />
                <SortHeader label="Segment"  sortKey="segment"         current={sort} setCurrent={setSort} />
                <SortHeader label="Channel"  sortKey="acquisition_channel" current={sort} setCurrent={setSort} />
                <SortHeader label="Acquired" sortKey="acquisition_date" current={sort} setCurrent={setSort} />
                <SortHeader label="Orders"   sortKey="order_count"     current={sort} setCurrent={setSort} align="right" />
                <SortHeader label="LTV"      sortKey="lifetime_value"  current={sort} setCurrent={setSort} align="right" />
                <SortHeader label="Last order" sortKey="last_order_date" current={sort} setCurrent={setSort} />
              </tr>
            </thead>
            <tbody>
              {sorted.map(r => (
                <tr key={r.id}>
                  <td style={{ paddingLeft: 14, fontWeight: 500 }}>{r.name}</td>
                  <td style={{ fontSize: 11.5, color: "var(--text-2)" }}>{r.email || "—"}</td>
                  <td style={{ fontSize: 11.5 }}>{r.segment || "—"}</td>
                  <td style={{ fontSize: 11.5, color: "var(--text-2)" }}>{r.acquisition_channel || "—"}</td>
                  <td style={{ fontFamily: "ui-monospace, monospace", fontSize: 11, color: "var(--text-3)" }}>{r.acquisition_date || "—"}</td>
                  <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace" }}>{r.order_count || 0}</td>
                  <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace" }}>{fmtUSD(r.lifetime_value, { compact: true })}</td>
                  <td style={{ fontFamily: "ui-monospace, monospace", fontSize: 11, color: "var(--text-3)" }}>{r.last_order_date || "—"}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </Card>
      )}
    </DataRoomShell>
  );
}

// ────────────────────────────────────────────────────────────────────────
// 6. AR / AP AGING
// ────────────────────────────────────────────────────────────────────────
function DataAgingPage({ scopedCompanyId, periodResolved, setPage }) {
  const companyId = useResolvedCompanyId(scopedCompanyId);
  const [loading, setLoading] = useDR_useState(true);
  const [txns, setTxns] = useDR_useState([]);
  const [mappings, setMappings] = useDR_useState([]);
  const [tab, setTab] = useDR_useState("ar");
  const [sort, setSort] = useDR_useState({ key: "age", dir: "desc" });

  useDR_useEffect(() => {
    if (!companyId) { setLoading(false); return; }
    setLoading(true);
    const db = window.supabaseClient;
    if (!db) { setLoading(false); return; }
    (async () => {
      const [{ data: rawTxns }, { data: rawMappings }] = await Promise.all([
        db.from("gl_transactions")
          .select("id, posted_date, account_code, account_name, amount, memo, reference")
          .eq("company_id", companyId)
          .order("posted_date", { ascending: false })
          .limit(10000),
        db.from("account_mappings")
          .select("account_code, canonical_category")
          .eq("company_id", companyId),
      ]);
      setTxns(rawTxns || []);
      setMappings(rawMappings || []);
      setLoading(false);
    })();
  }, [companyId]);

  const today = new Date();
  const buildRows = (category) => {
    const codes = new Set(mappings.filter(m => m.canonical_category === category).map(m => m.account_code));
    return txns.filter(tx => codes.has(tx.account_code)).map(tx => {
      const age = Math.floor((today - new Date(tx.posted_date)) / 86400000);
      return {
        ...tx,
        amount: parseFloat(tx.amount) || 0,
        age,
        bucket: age <= 0 ? "Current" : age <= 30 ? "1–30" : age <= 60 ? "31–60" : age <= 90 ? "61–90" : ">90",
      };
    });
  };

  const arRows = useDR_useMemo(() => buildRows("AR"), [txns, mappings]);
  const apRows = useDR_useMemo(() => buildRows("AP"), [txns, mappings]);

  const rows = tab === "ar" ? arRows : apRows;
  const sorted = useDR_useMemo(() => applySort(rows, sort), [rows, sort]);

  const csvHeaders = [
    { label: "Date",     value: "posted_date" }, { label: "Account",   value: "account_name" },
    { label: "Memo",     value: "memo" },        { label: "Reference", value: "reference" },
    { label: "Amount",   value: "amount" },      { label: "Age days",  value: "age" },
    { label: "Bucket",   value: "bucket" },
  ];

  const buckets = ["Current", "1–30", "31–60", "61–90", ">90"];
  const bucketTotals = buckets.map(b => ({
    label: b,
    count: rows.filter(r => r.bucket === b).length,
    value: rows.filter(r => r.bucket === b).reduce((s, r) => s + Math.abs(r.amount), 0),
  }));

  return (
    <DataRoomShell
      title="AR / AP Aging"
      subtitle="Open receivables and payables, bucketed by age. Driven by accounts mapped to AR / AP categories."
      action={
        <>
          <CSVDownload rows={sorted} headers={csvHeaders} filename={`aging_${tab}`} />
        </>
      }
    >
      {loading ? (
        <Card><div style={{ padding: 32, textAlign: "center", color: "var(--text-3)" }}>Loading…</div></Card>
      ) : (arRows.length === 0 && apRows.length === 0) ? (
        <EmptyState
          title="No AR / AP data yet"
          hint="Aging fills in once your GL is synced and the account mapping step assigns accounts to the 'AR' and 'AP' categories."
          onConnect={setPage ? () => setPage("settings_config") : null}
        />
      ) : (
        <>
          <div className="pc-section-tabs">
            <button className={tab === "ar" ? "active" : ""} onClick={() => setTab("ar")}>Receivables (AR · {arRows.length})</button>
            <button className={tab === "ap" ? "active" : ""} onClick={() => setTab("ap")}>Payables (AP · {apRows.length})</button>
          </div>

          <div className="pc-kpi-grid pc-kpi-grid-4" style={{ gridTemplateColumns: `repeat(${buckets.length}, 1fr)` }}>
            {bucketTotals.map(b => (
              <KPICard key={b.label} label={b.label} value={fmtUSD(b.value, { compact: true })} hint={`${b.count} item${b.count === 1 ? "" : "s"}`} accent={b.label === ">90" ? "var(--danger)" : "var(--accent)"} />
            ))}
          </div>

          <Card padding={0}>
            <table className="pc-table compact">
              <thead>
                <tr>
                  <SortHeader label="Date"      sortKey="posted_date"  current={sort} setCurrent={setSort} />
                  <SortHeader label="Account"   sortKey="account_name" current={sort} setCurrent={setSort} />
                  <th>Memo</th>
                  <SortHeader label="Reference" sortKey="reference"    current={sort} setCurrent={setSort} />
                  <SortHeader label="Amount"    sortKey="amount"       current={sort} setCurrent={setSort} align="right" />
                  <SortHeader label="Age (days)" sortKey="age"         current={sort} setCurrent={setSort} align="right" />
                  <SortHeader label="Bucket"    sortKey="bucket"       current={sort} setCurrent={setSort} />
                </tr>
              </thead>
              <tbody>
                {sorted.slice(0, 1000).map(r => (
                  <tr key={r.id} className={r.age > 60 ? "pc-row-danger" : ""}>
                    <td style={{ paddingLeft: 14, fontFamily: "ui-monospace, monospace", fontSize: 11 }}>{r.posted_date}</td>
                    <td>{r.account_name || "—"}</td>
                    <td style={{ fontSize: 11.5, color: "var(--text-2)", maxWidth: 320, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{r.memo}</td>
                    <td style={{ fontFamily: "ui-monospace, monospace", fontSize: 11, color: "var(--text-3)" }}>{r.reference}</td>
                    <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace" }}>{fmtUSD(Math.abs(r.amount), { compact: true })}</td>
                    <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace" }}>{r.age}</td>
                    <td><span className="pc-chip">{r.bucket}</span></td>
                  </tr>
                ))}
              </tbody>
            </table>
          </Card>
        </>
      )}
    </DataRoomShell>
  );
}

Object.assign(window, {
  DataTrialBalancePage, DataGeneralLedgerPage, DataSalesPage,
  DataInventoryPage, DataCustomersPage, DataAgingPage,
});
