// Phase 6b: all five read-only Finances routes. CSS/script wiring is documented
// in docs/phase6b-wiring.md; this file does not change another phase's globals.
(function () {
  const F = window.AreteFinances;
  const { useTables, Loading, LoadError, NoData, money, todayNY, FootToggle, Icon, usePhone, useWidth } = window;
  const amount = v => v === null ? "—" : money(v, 2);
  const caption = ym => F.monthLabel(ym);
  const numericColumns = rows => rows.map(r => ({ ...r, month: Number(r.ym.slice(5, 7)), year: Number(r.ym.slice(0, 4)) }));
  function Data({ tables, children }) {
    const t = useTables(tables);
    if (t.status === "loading") return <Loading />;
    if (t.status === "error") return <LoadError error={t.error} onRetry={t.reload} />;
    return <div className="finances">{children(t.data, todayNY())}</div>;
  }
  function TableBox({ title, children }) {
    return <div className="tcard scrollx finance-table" role="region" aria-label={title} tabIndex={0}>{children}</div>;
  }
  function Stats({ items }) {
    return <div className="finance-kpis">{items.map(([label, value, note]) => <div className="finance-kpi" key={label}>
      <div className="lab">{label}</div><div className="fig num">{amount(value)}</div><div className="lab">{note}</div>
    </div>)}</div>;
  }
  function Legend() {
    return <div className="finance-legend">
      {[["paid", "Revenue paid"], ["upcoming", "Revenue upcoming"], ["spent", "Expenses spent"], ["expected", "Expenses expected"]].map(([cls, label]) =>
        <span key={cls}><i className={"finance-swatch " + cls} aria-hidden="true" />{label}</span>)}
    </div>;
  }
  function Chart({ rows, today, kind = "bars" }) {
    const box = React.useRef(null), hits = React.useRef(null), scroller = React.useRef(null), refocus = React.useRef(false);
    const W = useWidth(box), phone = usePhone();
    const [selected, setSelected] = React.useState(() => window.AreteFinanceCharts.initialMonth(numericColumns(rows), today)), [hover, setHover] = React.useState(null);
    const sel = Math.min(selected, Math.max(0, rows.length - 1));
    const cols = numericColumns(rows), chart = window.AreteFinanceCharts[kind]({ cols, W, phone, sel });
    const shown = rows[hover ?? sel] || rows[sel];
    React.useLayoutEffect(() => {
      const hit = hits.current?.querySelector('[data-i="' + sel + '"]');
      if (refocus.current) hit?.focus({ preventScroll: true });
      refocus.current = false;
      if (hit && scroller.current) scroller.current.scrollLeft = Math.max(0,
        Number(hit.getAttribute("x")) + Number(hit.getAttribute("width")) / 2 - scroller.current.clientWidth / 2);
    }, [sel, W]);
    const index = e => {
      const hit = e.target.closest?.(".hit");
      return hit ? Number(hit.dataset.i) : null;
    };
    const keys = e => {
      const at = index(e);
      if (at === null) return;
      let next;
      if (e.key === "ArrowLeft") next = Math.max(0, at - 1);
      else if (e.key === "ArrowRight") next = Math.min(rows.length - 1, at + 1);
      else if (e.key === "Home") next = 0;
      else if (e.key === "End") next = rows.length - 1;
      else if (e.key === "Enter" || e.key === " ") next = at;
      else return;
      e.preventDefault(); refocus.current = true; setHover(null); setSelected(next);
    };
    const values = r => kind === "cash" ? [["Cash in", r.cashIn], ["Cash out", r.cashOut], ["Running total", r.running]] :
      [["Revenue paid", r.paid], ["Revenue upcoming", r.upcoming], ["Expenses spent", r.spent], ["Expenses expected", r.expected]];
    return <div ref={box}>
      <p className="sr">{kind === "cash" ? "Running bank cash flow, including mortgage and improvements." : "Monthly revenue and expenses, split into actual and expected amounts."} Use Left and Right arrows to read each month. The table below has the same numbers.</p>
      <div ref={scroller} className="finance-chart scrollx" onMouseLeave={() => setHover(null)}>
        <div ref={hits} style={{ minWidth: chart.width }} onKeyDown={keys}
          onMouseMove={e => setHover(index(e))} onFocus={e => { const i = index(e); if (i !== null) setSelected(i); }}
          onClick={e => { const i = index(e); if (i !== null) { setHover(null); setSelected(i); } }}
          dangerouslySetInnerHTML={{ __html: chart.svg }} />
      </div>
      {shown && <div className="finance-readout" role="status" aria-live="polite">
        <b>{caption(shown.ym)}</b>{values(shown).map(([name, value]) => <span key={name}>{name}: <b className="num">{amount(value)}</b></span>)}
      </div>}
    </div>;
  }
  function Overview({ data, today }) {
    const [year, setYear] = React.useState(today.slice(0, 4)), [table, setTable] = React.useState(false);
    const b = F.budget(data.reservations, data.transactions, data.recurring_costs, { today });
    const all = F.overview(data.reservations, data.transactions, b, { today });
    const years = Object.keys(all), selectedYear = all[year] ? year : years[0], rows = all[selectedYear];
    if (!data.reservations.length && !data.transactions.length && !data.recurring_costs.length) return <NoData>No finance data yet.</NoData>;
    const totals = rows.reduce((a, r) => ({ paid: a.paid + r.paid, upcoming: a.upcoming + r.upcoming,
      spent: a.spent + r.spent, expected: a.expected === null || r.expected === null ? null : a.expected + r.expected }), { paid: 0, upcoming: 0, spent: 0, expected: 0 });
    return <>
      <Stats items={[
        ["Revenue " + selectedYear, totals.paid + totals.upcoming, `${money(totals.paid)} paid · ${money(totals.upcoming)} upcoming`],
        ["Expenses " + selectedYear, totals.expected === null ? null : totals.spent + totals.expected, `${money(totals.spent)} spent · ${amount(totals.expected)} expected`],
        ["Profit " + selectedYear, totals.expected === null ? null : totals.paid + totals.upcoming - totals.spent - totals.expected, "Revenue − expenses, full year"],
      ]} />
      <section><div className="secthead"><h2>By month</h2><label className="finance-year">Year <select value={selectedYear} onChange={e => setYear(e.target.value)}>{years.map(y => <option key={y}>{y}</option>)}</select></label></div>
        {!data.reservations.length && <NoData>No reservations loaded. Revenue is zero.</NoData>}
        {!data.transactions.length && <NoData>No ledger transactions loaded. Actual spending is unknown.</NoData>}
        {totals.expected === null ? <NoData>Expected costs need more P&amp;L data: {b.missing.join(", ")}. Show the table to see actual amounts. A dash means unknown.</NoData> :
          <><Legend /><Chart key={selectedYear} rows={rows} today={today} /></>}
        <button className="showtable" aria-expanded={table} onClick={() => setTable(v => !v)}>{table ? "Hide" : "Show as"} table</button>
        {table && <TableBox title="Revenue and expenses by month"><table className="tbl side"><caption className="sr">Revenue and expenses {selectedYear}</caption>
          <thead><tr><th>Month</th><th className="r">Revenue paid</th><th className="r">Upcoming</th><th className="r">Spent</th><th className="r">Expected</th><th className="r">Profit</th></tr></thead>
          <tbody>{rows.map(r => <tr key={r.ym}><th scope="row">{caption(r.ym)}</th>{[r.paid, r.upcoming, r.spent, r.expected, r.expected === null ? null : r.paid + r.upcoming - r.spent - r.expected].map((v, i) => <td className="r num" key={i}>{amount(v)}</td>)}</tr>)}</tbody>
        </table></TableBox>}
        <p className="finance-note">Revenue is payout after OTA fees, in the check-in month. Spent is ledger expense since opening, including mortgage interest. Expected uses average monthly P&amp;L operating expenses plus mortgage principal + interest, as in the old dashboard. The P&amp;L cost lines include cleaning and escrow-funded tax and insurance. Future months show that full budget.</p>
        <p className="finance-note">Current-month expected = max(0, P&amp;L operating expense average + mortgage principal + interest − actual spending). Past months show zero expected. Bills are not linked to posted payments, so this is an estimate, not a list of unpaid bills.</p>
      </section>
    </>;
  }
  function Pnl({ data, today }) {
    const [picked, setPicked] = React.useState("avg"), [side, setSide] = React.useState(false);   // opens on "Average (full months)", as in the mockup
    const b = F.budget(data.reservations, data.transactions, data.recurring_costs, { today });
    if (!data.transactions.length || !b.pills.length) return <NoData>No live-month ledger data yet.</NoData>;
    const ym = picked === "avg" || b.pills.includes(picked) ? picked : b.pills.at(-1), c = F.pnlCol(b, ym), average = ym === "avg";
    const s = b.sources;
    const source = row => row ? `${row.vendor}; register budget ${amount(row.monthlyBudget)}/month; pushed ${row.pushedAt?.slice(0, 10) || "date unknown"}` : "register row missing";
    const subtitle = average ? (b.completeMonths.length ? `Full months: ${b.completeMonths.map(caption).join(", ")}` : "No full live month yet") :
      caption(ym) + (ym === today.slice(0, 7) ? " · so far" : b.partialYms.includes(ym) ? " · partial opening month" : " · actual");
    const summary = [["Revenue (after OTA fees)", "rev"], ["Total operating expenses", "opex"], ["Net operating income", "noi"], ["Mortgage (principal + interest)", "debt"], ["Cash flow", "cash"]];
    const note = (line, key) => key === "avg" ? line.basis : line.method === "escrow" ? "Escrow allocation for a month with a mortgage payment" : "Actual signed ledger costs for " + caption(key);
    return <>
      <p className="sub">What a month costs, what it earns, and what is left after the mortgage.</p>
      <div className="statsrow finance-pills" role="group" aria-label="P&L month">
        <button className={"filter" + (average ? " on" : "")} aria-pressed={average} onClick={() => setPicked("avg")}>Average (full months)</button>
        {b.pills.map(m => <button className={"filter" + (m === ym ? " on" : "")} aria-pressed={m === ym} key={m} onClick={() => setPicked(m)}>{caption(m)}{m === today.slice(0, 7) ? " · so far" : b.partialYms.includes(m) ? " · partial" : ""}</button>)}
      </div>
      <div className="finance-note">
        <div>Insurance: {source(s.insurance)}; using {s.insuranceAnnualQuote !== null ? `prior “was” quote ${amount(s.insuranceAnnualQuote)}/year ÷ 12` : "monthly register budget"} = {amount(s.insuranceMonthly)}/month.</div>
        <div>Mortgage register: {source(s.mortgage)} (full principal + interest + escrow payment).</div>
        <div>P&amp;I: {average || c.debtFallback ? `register mortgage minus latest ledger escrow ${amount(s.escrow)} (${s.escrowDate || "date unknown"}) = ${amount(b.debtPI)}` : `ledger mortgage-interest + transfer-principal for ${caption(ym)}`}{c.debtFallback ? "; no payment found this month" : ""}.</div>
      </div>
      {b.missing.length > 0 && <NoData>Some averages need more data: {b.missing.join(", ")}. A dash means unknown.</NoData>}
      {!data.reservations.length && <NoData>No reservations loaded. Revenue is zero for the months shown.</NoData>}
      <div className="card">
        <div className="in"><h3>{average ? "Average month" : caption(ym)}<span className="th2">{subtitle}</span></h3>
          <div className="trio">{[["Revenue", c.rev], ["Expenses + mortgage", c.opex === null || c.debt === null ? null : c.opex + c.debt], ["Cash flow", c.cash]].map(([label, v]) => <div key={label}><div className="fig num">{amount(v)}</div><div className="lab">{label}</div></div>)}</div>
        </div>
        <div className="pace"><div className="scrollx finance-table" role="region" aria-label="Monthly profit and loss" tabIndex={0}>
          <table className="tbl finance-pnl"><caption className="sr">Monthly P&amp;L: {subtitle}</caption><thead><tr><th>Line</th><th className="r">Amount</th><th>How it is calculated</th></tr></thead><tbody>
            <tr className="us"><th scope="row">Revenue<span className="th2">after OTA fees</span></th><td className="r num">{amount(c.rev)}</td><td className="finance-basis">{average ? b.revSrc : "Paid check-ins in this month; upcoming stays excluded"}</td></tr>
            {F.GROUPS.map(group => <React.Fragment key={group}><tr className="grp"><th colSpan={3} scope="rowgroup">{group}</th></tr>
              {b.lines.map((l, i) => l.group === group && <tr key={l.id}><th scope="row">{l.label}</th><td className="r num">{amount(c.lines[i])}</td><td className="finance-basis">{note(l, ym)}</td></tr>)}
            </React.Fragment>)}
            <tr className="us"><th scope="row">Total operating expenses</th><td className="r num">{amount(c.opex)}</td><td className="finance-basis">Sum of the cost lines above</td></tr>
            <tr className="us"><th scope="row">Net operating income</th><td className="r num">{amount(c.noi)}</td><td className="finance-basis">Revenue − operating expenses</td></tr>
            <tr><th scope="row">Mortgage<span className="th2">principal + interest</span></th><td className="r num">{amount(c.debt)}</td><td className="finance-basis">{average ? "Contract payment less escrow" : c.debtFallback ? "No payment found this month; showing contract principal + interest" : "Actual mortgage interest + principal"}. Escrow is in the lines above.</td></tr>
            <tr className="us finance-total"><th scope="row">Cash flow</th><td className="r num">{amount(c.cash)}</td><td className="finance-basis">Net operating income − mortgage (principal + interest)</td></tr>
          </tbody></table>
        </div></div>
        <FootToggle open={side} onClick={() => setSide(v => !v)} show="Show all months side by side" hide="Hide all months side by side" />
        {side && <div className="pace"><div className="scrollx finance-table" role="region" aria-label="All P&L months" tabIndex={0}><table className="tbl side">
          <caption className="sr">All P&amp;L months side by side</caption><thead><tr><th>Line</th><th className="r">Average</th>{b.pills.map(m => <th className="r" key={m}>{caption(m)}{b.partialYms.includes(m) && <span className="th2">{m === today.slice(0, 7) ? "so far" : "partial"}</span>}</th>)}</tr></thead>
          <tbody>{[summary[0], ...b.lines.map((l, i) => [l.label, i]), ...summary.slice(1)].map(([label, key]) => <tr key={label} className={label === "Cash flow" ? "us" : ""}><th scope="row">{label}</th>{["avg", ...b.pills].map(m => { const col = F.pnlCol(b, m); return <td className="r num" key={m}>{amount(typeof key === "number" ? col.lines[key] : col[key])}</td>; })}</tr>)}</tbody>
        </table></div></div>}
      </div>
      <p className="finance-note">One-time launch costs are left out. Revenue is already net of OTA fees. Billed costs include pre-opening history; booking-cost averages exclude partial months. These lines preserve the old Monthly budget rules, including its separate MyCurbAppeal line and repairs category.</p>
    </>;
  }
  function Categories({ data, today }) {
    const c = F.categories(data.transactions, { today });
    if (!c.rows.length) return <NoData>No operating expenses since opening.</NoData>;
    const max = Math.max(1, ...c.rows.map(r => Math.abs(r.total)));
    return <><p className="sub">Since opening (May 15, 2026) · ledger operating expenses · refunds reduce cost</p>
      {c.rows.map(row => <div className="finance-hbar" key={row.category}><span className="n">{row.category}</span><span className="b" aria-hidden="true"><i style={{ width: Math.abs(row.total) / max * 100 + "%" }} /></span><span className="v num">{amount(row.total)}</span></div>)}
      <section className="finance-section"><div className="secthead"><h2>By month</h2></div>
        <TableBox title="Expense categories by month"><table className="tbl side"><caption className="sr">Expenses by category and month</caption><thead><tr><th>Category</th>{c.months.map(m => <th className="r" key={m}>{caption(m)}{m === today.slice(0, 7) && <span className="th2">so far</span>}</th>)}<th className="r">Total</th></tr></thead>
          <tbody>{c.rows.map(row => <tr key={row.category}><th scope="row">{row.category}</th>{[...row.monthly, row.total].map((v, i) => <td className="r num" key={i}>{amount(v)}</td>)}</tr>)}
            <tr className="us"><th scope="row">Total</th>{[...c.monthly, c.total].map((v, i) => <td className="r num" key={i}>{amount(v)}</td>)}</tr>
          </tbody></table></TableBox>
      </section></>;
  }
  function Bills({ data }) {
    const b = F.bills(data.recurring_costs);
    if (!b.count) return <NoData>No active recurring costs yet.</NoData>;
    return <><p className="sub">{b.count} active bills · {b.watch} to check · {money(b.monthlyBudget)} in monthly register budgets</p>
      <p className="finance-note">{b.unbudgeted} bills have no monthly budget, including per-booking costs. Escrow bills can also be included in the mortgage payment; this register total is not the P&amp;L expense total.</p>
      {b.groups.map(g => <section className="finance-bills" key={g.group}><div className="secthead"><h2>{g.group}</h2><span className="dd">{g.rows.length} {g.rows.length === 1 ? "bill" : "bills"}</span></div>
        <TableBox title={g.group + " recurring bills"}><table className="tbl stack fixed"><caption className="sr">{g.group}</caption><thead><tr><th>Vendor</th><th className="r">Amount</th><th>When</th><th>Paid from</th><th>Status</th></tr></thead><tbody>
          {g.rows.map((r, i) => <tr key={r.id || i}><td data-l="Vendor"><div className="d1">{r.vendor}</div><div className="d2">{r.what}</div></td><td data-l="Amount" className="r num">{r.amount_text || "Not set"}</td><td data-l="When">{r.when_text || "Not set"}</td><td data-l="Paid from">{r.paid_from || "Not set"}</td><td data-l="Status"><span className={"finance-status " + r.status}>{r.status === "watch" ? <span aria-hidden="true">!</span> : <Icon name="check" size={16} />}{r.status === "watch" ? "Watch · to check" : "OK"}</span>{r.note && <span className="th2">{r.note}</span>}</td></tr>)}
        </tbody></table></TableBox>
      </section>)}</>;
  }
  function Cash({ data, today }) {
    const [show, setShow] = React.useState(true);
    const c = F.cashFlow(data.transactions, { today });
    if (!c.months.length) return <NoData>No bank cash flow yet.</NoData>;
    return <>
      <Stats items={[["Cash in", c.cashIn, "Bank deposits and other income"], ["Cash out", c.cashOut, "Expenses, full mortgage and improvements"], ["Running total", c.net, "Net change from the first ledger month"]]} />
      <section><div className="secthead"><h2>Cash flow by month</h2></div><Chart kind="cash" rows={c.months} today={today} />
        <button className="showtable" aria-expanded={show} onClick={() => setShow(v => !v)}>{show ? "Hide table" : "Show as table"}</button>
        {show && <TableBox title="Monthly bank cash flow"><table className="tbl side"><caption className="sr">Monthly cash flow, mortgage included</caption><thead><tr><th>Month</th><th className="r">Cash in</th><th className="r">Cash out</th><th className="r">Net cash</th><th className="r">Running total</th></tr></thead><tbody>
          {c.months.map(m => <tr key={m.ym}><th scope="row">{caption(m.ym)}{m.partial && <span className="th2">so far</span>}</th>{[m.cashIn, m.cashOut, m.net, m.running].map((v, i) => <td className="r num" key={i}>{amount(v)}</td>)}</tr>)}
          <tr className="us"><th scope="row">Total</th>{[c.cashIn, c.cashOut, c.net, c.net].map((v, i) => <td className="r num" key={i}>{amount(v)}</td>)}</tr>
        </tbody></table></TableBox>}
        <p className="finance-note">Bank-date basis through {today}. Cash out includes operating expenses, improvements, mortgage principal and escrow. Interest is counted once within expenses. Owner contributions, draws and card-payment transfers are excluded. The running total starts at zero; it is not an account balance.</p>
      </section>
    </>;
  }
  function OverviewPage() { return <Data tables={["reservations", "transactions", "recurring_costs"]}>{(data, today) => <Overview data={data} today={today} />}</Data>; }
  function PnlPage() { return <Data tables={["reservations", "transactions", "recurring_costs"]}>{(data, today) => <Pnl data={data} today={today} />}</Data>; }
  function CategoriesPage() { return <Data tables={["transactions"]}>{(data, today) => <Categories data={data} today={today} />}</Data>; }
  function BillsPage() { return <Data tables={["recurring_costs"]}>{data => <Bills data={data} />}</Data>; }
  function CashPage() { return <Data tables={["transactions"]}>{(data, today) => <Cash data={data} today={today} />}</Data>; }
  window.ARETE_PAGES = Object.assign(window.ARETE_PAGES || {}, {
    "finances/overview": OverviewPage, "finances/pnl": PnlPage, "finances/categories": CategoriesPage,
    "finances/bills": BillsPage, "finances/cash": CashPage,
  });
})();
