/**
 * Shared Ledger page — tabs for Work Log, Payments, Expenses.
 * Left: hierarchical spreadsheet + entry form + summary stats.
 * Right: configurable charts.
 */

import React, { useMemo, useState } from 'react';
import { useAppStore } from '@/store/appStore';
import type { WorkEntry, Payment, Expense, RecurringExpense, RecurringFrequency, LedgerTile } from '@/types';
import { workEntryValue } from '@/types';
import { HierSpreadsheet } from '@/components/spreadsheet/HierSpreadsheet';
import { WorkEntryForm, PaymentForm, ExpenseForm } from '@/components/spreadsheet/EntryForm';
import { ChartSidebar } from '@/components/charts/ChartSidebar';
import { ResizableSplit } from '@/components/layout/ResizableSplit';
import { Modal, ConfirmDialog } from '@/components/common/Modal';
import { buildHierarchyForRange, buildHierarchy, aggregate } from '@/lib/stats/aggregate';
import { fmtMoney, todayISO, nowInTZ } from '@/lib/format';

function yearStart() { return `${new Date().getFullYear()}-01-01`; }

/** Sort unique string values by frequency (desc), with the most-recently-used value first. */
function freqSorted(values: Array<{ value: string; createdAt: number }>): string[] {
  const freq = new Map<string, number>();
  let mruValue = '';
  let mruTime = 0;
  for (const { value, createdAt } of values) {
    if (!value) continue;
    freq.set(value, (freq.get(value) ?? 0) + 1);
    if (createdAt > mruTime) { mruTime = createdAt; mruValue = value; }
  }
  const sorted = [...freq.keys()].sort((a, b) => (freq.get(b) ?? 0) - (freq.get(a) ?? 0));
  if (mruValue) {
    const i = sorted.indexOf(mruValue);
    if (i > 0) { sorted.splice(i, 1); sorted.unshift(mruValue); }
  }
  return sorted;
}

function usePersistedDate(key: string): [string, (v: string) => void] {
  const [value, setValue] = useState(() => localStorage.getItem(key) ?? yearStart());
  const set = (v: string) => { setValue(v); localStorage.setItem(key, v); };
  return [value, set];
}

type Tab = 'work' | 'payments' | 'expenses';

export function LedgerPage({ initialTab = 'work' }: { initialTab?: Tab }) {
  const [workStart, setWorkStart] = usePersistedDate('ledger_work_from');
  const [paymentsStart, setPaymentsStart] = usePersistedDate('ledger_payments_from');
  const [expensesStart, setExpensesStart] = usePersistedDate('ledger_expenses_from');
  const today = todayISO();

  const startDate =
    initialTab === 'work' ? workStart :
    initialTab === 'payments' ? paymentsStart :
    expensesStart;

  return (
    <ResizableSplit
      left={
        <>
          {initialTab === 'work' && <WorkTab startDate={workStart} setStartDate={setWorkStart} />}
          {initialTab === 'payments' && <PaymentsTab startDate={paymentsStart} setStartDate={setPaymentsStart} />}
          {initialTab === 'expenses' && <ExpensesTab startDate={expensesStart} setStartDate={setExpensesStart} />}
        </>
      }
      right={<ChartSidebar tab={initialTab} defaultRangeStart={startDate} defaultRangeEnd={today} />}
    />
  );
}

// ─── Work Tab ────────────────────────────────────────────────────────────────

function WorkTab({ startDate, setStartDate }: { startDate: string; setStartDate: (v: string) => void }) {
  const entries = useAppStore((s) => s.data.workEntries);
  const defaultRate = useAppStore((s) => s.data.settings.defaultRate);
  const addWorkEntry = useAppStore((s) => s.addWorkEntry);
  const updateWorkEntry = useAppStore((s) => s.updateWorkEntry);
  const deleteWorkEntry = useAppStore((s) => s.deleteWorkEntry);
  const tiles = useAppStore((s) => s.data.dashboard.workTiles);
  const setPageTiles = useAppStore((s) => s.setPageTiles);

  const [addForDay, setAddForDay] = useState<string | null>(null);
  const [editing, setEditing] = useState<WorkEntry | null>(null);
  const [deleting, setDeleting] = useState<string | null>(null);
  const [configOpen, setConfigOpen] = useState(false);

  const today = todayISO();

  const nodes = useMemo(
    () =>
      buildHierarchyForRange(
        entries,
        startDate,
        today,
        (e) => workEntryValue(e as WorkEntry),
        (e) => {
          const w = e as WorkEntry;
          const extra = w.hours != null ? ` (${w.hours}h @ $${w.rate})` : '';
          return `${w.description}${extra}${w.client ? ` — ${w.client}` : ''}`;
        },
      ),
    [entries, startDate, today],
  );

  const stats = useMemo(() => aggregate(entries, [], []), [entries]);

  const existingClients = useMemo(
    () => freqSorted(entries.map((e) => ({ value: e.client ?? '', createdAt: e.createdAt }))),
    [entries],
  );
  const existingDescriptions = useMemo(
    () => freqSorted(entries.map((e) => ({ value: e.description, createdAt: e.createdAt }))),
    [entries],
  );

  return (
    <>
      <PeriodSummaryRow
        stats={stats}
        metric="workValue"
        label="Work value"
        tiles={tiles}
        onConfigure={() => setConfigOpen(true)}
      />

      <div className="card" style={{ display: 'flex', flexDirection: 'column' }}>
        <div className="card-header">
          <span className="card-title">Work Log</span>
          <div className="flex items-center gap-2">
            <label className="text-sm text-muted">From</label>
            <input
              type="date"
              className="input"
              style={{ width: 148, height: 32 }}
              value={startDate}
              onChange={(e) => setStartDate(e.target.value)}
            />
            <button className="btn btn-primary btn-sm" onClick={() => setAddForDay(today)}>
              + Add entry
            </button>
          </div>
        </div>
        <HierSpreadsheet
          nodes={nodes}
          valueLabel="Earned"
          onAddForDay={(date) => setAddForDay(date)}
          onView={(n) => setEditing(n.entry as WorkEntry)}
          onEdit={(n) => setEditing(n.entry as WorkEntry)}
          onDelete={(n) => setDeleting(n.entry!.id)}
          onToggleOutstanding={(n) => {
            const e = n.entry as WorkEntry;
            updateWorkEntry(e.id, { paymentOutstanding: !e.paymentOutstanding });
          }}
        />
      </div>

      <Modal open={addForDay != null} title="Add work entry" onClose={() => setAddForDay(null)}>
        {addForDay != null && (
          <WorkEntryForm
            initial={{ date: addForDay }}
            defaultRate={defaultRate}
            existingClients={existingClients}
            existingDescriptions={existingDescriptions}
            onSubmit={(d) => { addWorkEntry(d); setAddForDay(null); }}
            onCancel={() => setAddForDay(null)}
          />
        )}
      </Modal>

      <Modal open={editing != null} title="Edit work entry" onClose={() => setEditing(null)}>
        {editing && (
          <WorkEntryForm
            initial={editing}
            defaultRate={defaultRate}
            existingClients={existingClients}
            existingDescriptions={existingDescriptions}
            onSubmit={(d) => { updateWorkEntry(editing.id, d); setEditing(null); }}
            onCancel={() => setEditing(null)}
          />
        )}
      </Modal>

      <ConfirmDialog
        open={deleting != null}
        title="Delete work entry?"
        message="This cannot be undone."
        confirmLabel="Delete"
        danger
        onConfirm={() => { if (deleting) deleteWorkEntry(deleting); setDeleting(null); }}
        onCancel={() => setDeleting(null)}
      />

      <TileConfigModal
        open={configOpen}
        tiles={tiles}
        onChange={(t) => setPageTiles('work', t)}
        onClose={() => setConfigOpen(false)}
      />
    </>
  );
}

// ─── Payments Tab ────────────────────────────────────────────────────────────

function PaymentsTab({ startDate, setStartDate }: { startDate: string; setStartDate: (v: string) => void }) {
  const payments = useAppStore((s) => s.data.payments);
  const addPayment = useAppStore((s) => s.addPayment);
  const updatePayment = useAppStore((s) => s.updatePayment);
  const deletePayment = useAppStore((s) => s.deletePayment);
  const tiles = useAppStore((s) => s.data.dashboard.paymentsTiles);
  const setPageTiles = useAppStore((s) => s.setPageTiles);

  const [addForDay, setAddForDay] = useState<string | null>(null);
  const [editing, setEditing] = useState<Payment | null>(null);
  const [deleting, setDeleting] = useState<string | null>(null);
  const [configOpen, setConfigOpen] = useState(false);

  const today = todayISO();

  const nodes = useMemo(
    () =>
      buildHierarchyForRange(
        payments,
        startDate,
        today,
        (e) => (e as Payment).amount,
        (e) => {
          const p = e as Payment;
          return `${p.payer} (${p.form ?? 'direct'})${p.notes ? ` — ${p.notes}` : ''}`;
        },
      ),
    [payments, startDate, today],
  );

  const stats = useMemo(() => aggregate([], payments, []), [payments]);

  const recentForm = useMemo(
    () => payments.slice().sort((a, b) => b.createdAt - a.createdAt)[0]?.form,
    [payments],
  );

  const existingPayers = useMemo(
    () => freqSorted(payments.map((p) => ({ value: p.payer, createdAt: p.createdAt }))),
    [payments],
  );

  return (
    <>
      <PeriodSummaryRow
        stats={stats}
        metric="payments"
        label="Taxable income"
        tiles={tiles}
        onConfigure={() => setConfigOpen(true)}
      />

      <div className="card" style={{ display: 'flex', flexDirection: 'column' }}>
        <div className="card-header">
          <span className="card-title">Payments Received</span>
          <div className="flex items-center gap-2">
            <label className="text-sm text-muted">From</label>
            <input
              type="date"
              className="input"
              style={{ width: 148, height: 32 }}
              value={startDate}
              onChange={(e) => setStartDate(e.target.value)}
            />
            <button className="btn btn-primary btn-sm" onClick={() => setAddForDay(today)}>
              + Add payment
            </button>
          </div>
        </div>
        <HierSpreadsheet
          nodes={nodes}
          valueLabel="Amount"
          onAddForDay={(date) => setAddForDay(date)}
          onView={(n) => setEditing(n.entry as Payment)}
          onEdit={(n) => setEditing(n.entry as Payment)}
          onDelete={(n) => setDeleting(n.entry!.id)}
        />
      </div>

      <Modal open={addForDay != null} title="Add payment" onClose={() => setAddForDay(null)}>
        {addForDay != null && (
          <PaymentForm
            initial={{ date: addForDay }}
            defaultForm={recentForm}
            existingPayers={existingPayers}
            onSubmit={(d) => { addPayment(d); setAddForDay(null); }}
            onCancel={() => setAddForDay(null)}
          />
        )}
      </Modal>

      <Modal open={editing != null} title="Edit payment" onClose={() => setEditing(null)}>
        {editing && (
          <PaymentForm
            initial={editing}
            existingPayers={existingPayers}
            onSubmit={(d) => { updatePayment(editing.id, d); setEditing(null); }}
            onCancel={() => setEditing(null)}
          />
        )}
      </Modal>

      <ConfirmDialog
        open={deleting != null}
        title="Delete payment?"
        message="This cannot be undone."
        confirmLabel="Delete"
        danger
        onConfirm={() => { if (deleting) deletePayment(deleting); setDeleting(null); }}
        onCancel={() => setDeleting(null)}
      />

      <TileConfigModal
        open={configOpen}
        tiles={tiles}
        onChange={(t) => setPageTiles('payments', t)}
        onClose={() => setConfigOpen(false)}
      />
    </>
  );
}

// ─── Expenses Tab ────────────────────────────────────────────────────────────

function ExpensesTab({ startDate, setStartDate }: { startDate: string; setStartDate: (v: string) => void }) {
  const expenses = useAppStore((s) => s.data.expenses);
  const addExpense = useAppStore((s) => s.addExpense);
  const updateExpense = useAppStore((s) => s.updateExpense);
  const deleteExpense = useAppStore((s) => s.deleteExpense);
  const recurringExpenses = useAppStore((s) => s.data.recurringExpenses);
  const addRecurringExpense = useAppStore((s) => s.addRecurringExpense);
  const updateRecurringExpense = useAppStore((s) => s.updateRecurringExpense);
  const deleteRecurringExpense = useAppStore((s) => s.deleteRecurringExpense);

  const tiles = useAppStore((s) => s.data.dashboard.expensesTiles);
  const setPageTiles = useAppStore((s) => s.setPageTiles);

  const [showAdd, setShowAdd] = useState(false);
  const [editing, setEditing] = useState<Expense | null>(null);
  const [deleting, setDeleting] = useState<string | null>(null);
  const [showRecurring, setShowRecurring] = useState(false);
  const [editingRecurring, setEditingRecurring] = useState<RecurringExpense | null>(null);
  const [deletingRecurring, setDeletingRecurring] = useState<string | null>(null);
  const [configOpen, setConfigOpen] = useState(false);

  const today = todayISO();

  const nodes = useMemo(
    () =>
      buildHierarchyForRange(
        expenses,
        startDate,
        today,
        (e) => (e as Expense).amount,
        (e) => {
          const x = e as Expense;
          return `${x.description}${x.deductible ? ' ✓ deductible' : ''}${x.category ? ` — ${x.category}` : ''}`;
        },
      ),
    [expenses, startDate, today],
  );

  const stats = useMemo(() => aggregate([], [], expenses), [expenses]);

  return (
    <>
      <PeriodSummaryRow
        stats={stats}
        metric="expenses"
        label="Expenses"
        tiles={tiles}
        onConfigure={() => setConfigOpen(true)}
      />

      <div className="card" style={{ display: 'flex', flexDirection: 'column' }}>
        <div className="card-header">
          <span className="card-title">Expenses</span>
          <div className="flex items-center gap-2">
            <label className="text-sm text-muted">From</label>
            <input
              type="date"
              className="input"
              style={{ width: 148, height: 32 }}
              value={startDate}
              onChange={(e) => setStartDate(e.target.value)}
            />
            <button className="btn btn-primary btn-sm" onClick={() => setShowAdd(true)}>
              + Add expense
            </button>
          </div>
        </div>
        <HierSpreadsheet
          nodes={nodes}
          valueLabel="Amount"
          onView={(n) => setEditing(n.entry as Expense)}
          onEdit={(n) => setEditing(n.entry as Expense)}
          onDelete={(n) => setDeleting(n.entry!.id)}
        />
      </div>

      <Modal open={showAdd} title="Add expense" onClose={() => setShowAdd(false)}>
        <ExpenseForm onSubmit={(d) => { addExpense(d); setShowAdd(false); }} onCancel={() => setShowAdd(false)} />
      </Modal>

      <Modal open={editing != null} title="Edit expense" onClose={() => setEditing(null)}>
        {editing && (
          <ExpenseForm
            initial={editing}
            onSubmit={(d) => { updateExpense(editing.id, d); setEditing(null); }}
            onCancel={() => setEditing(null)}
          />
        )}
      </Modal>

      <ConfirmDialog
        open={deleting != null}
        title="Delete expense?"
        message="This cannot be undone."
        confirmLabel="Delete"
        danger
        onConfirm={() => { if (deleting) deleteExpense(deleting); setDeleting(null); }}
        onCancel={() => setDeleting(null)}
      />

      {/* ─── Recurring expenses ─────────────────────────── */}
      <div className="card" style={{ display: 'flex', flexDirection: 'column' }}>
        <div className="card-header">
          <span className="card-title">Recurring Expenses</span>
          <button className="btn btn-primary btn-sm" onClick={() => setShowRecurring(true)}>
            + Add recurring
          </button>
        </div>
        {recurringExpenses.length === 0 ? (
          <div className="text-muted text-sm" style={{ padding: '12px 16px' }}>
            No recurring expenses set up. Add one to auto-generate expense entries.
          </div>
        ) : (
          <table className="data-table">
            <thead>
              <tr>
                <th>Description</th>
                <th className="num">Amount</th>
                <th>Frequency</th>
                <th>Since</th>
                <th>Category</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {recurringExpenses.map((r) => (
                <tr key={r.id}>
                  <td>{r.description}{r.deductible ? ' ✓' : ''}</td>
                  <td className="num">${r.amount.toFixed(2)}</td>
                  <td className="text-sm">{r.frequency}</td>
                  <td className="text-sm text-muted">{r.startDate}</td>
                  <td className="text-sm text-muted">{r.category ?? '—'}</td>
                  <td>
                    <div className="flex gap-1">
                      <button className="btn btn-sm btn-ghost" onClick={() => setEditingRecurring(r)} title="Edit">✎</button>
                      <button className="btn btn-sm btn-ghost text-danger" onClick={() => setDeletingRecurring(r.id)} title="Delete">✕</button>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>

      <Modal open={showRecurring} title="Add recurring expense" onClose={() => setShowRecurring(false)}>
        <RecurringExpenseForm
          onSubmit={(d) => { addRecurringExpense(d); setShowRecurring(false); }}
          onCancel={() => setShowRecurring(false)}
        />
      </Modal>

      <Modal open={editingRecurring != null} title="Edit recurring expense" onClose={() => setEditingRecurring(null)}>
        {editingRecurring && (
          <RecurringExpenseForm
            initial={editingRecurring}
            onSubmit={(d) => { updateRecurringExpense(editingRecurring.id, d); setEditingRecurring(null); }}
            onCancel={() => setEditingRecurring(null)}
          />
        )}
      </Modal>

      <ConfirmDialog
        open={deletingRecurring != null}
        title="Delete recurring expense?"
        message="This removes the template but keeps existing expense entries already created from it."
        confirmLabel="Delete"
        danger
        onConfirm={() => { if (deletingRecurring) deleteRecurringExpense(deletingRecurring); setDeletingRecurring(null); }}
        onCancel={() => setDeletingRecurring(null)}
      />

      <TileConfigModal
        open={configOpen}
        tiles={tiles}
        onChange={(t) => setPageTiles('expenses', t)}
        onClose={() => setConfigOpen(false)}
      />
    </>
  );
}

// ─── Recurring expense form ───────────────────────────────────────────────────

type RecurringDraft = Omit<RecurringExpense, 'id' | 'createdAt' | 'updatedAt'>;

const FREQ_LABELS: Record<RecurringFrequency, string> = {
  weekly: 'Weekly', biweekly: 'Bi-weekly', monthly: 'Monthly',
  quarterly: 'Quarterly', annually: 'Annually',
};

function RecurringExpenseForm({
  initial,
  onSubmit,
  onCancel,
}: {
  initial?: Partial<RecurringDraft>;
  onSubmit: (d: RecurringDraft) => void;
  onCancel: () => void;
}) {
  const [desc, setDesc] = useState(initial?.description ?? '');
  const [amount, setAmount] = useState(initial?.amount?.toString() ?? '');
  const [category, setCategory] = useState(initial?.category ?? '');
  const [deductible, setDeductible] = useState(initial?.deductible ?? true);
  const [frequency, setFrequency] = useState<RecurringFrequency>(initial?.frequency ?? 'monthly');
  const [dayOfMonth, setDayOfMonth] = useState(initial?.dayOfMonth?.toString() ?? '1');
  const [startDate, setStartDate] = useState(initial?.startDate ?? todayISO());
  const [endDate, setEndDate] = useState(initial?.endDate ?? '');

  const submit = (e: React.FormEvent) => {
    e.preventDefault();
    onSubmit({
      description: desc, amount: parseFloat(amount) || 0,
      category: category || undefined, deductible, frequency,
      dayOfMonth: parseInt(dayOfMonth) || 1,
      startDate, endDate: endDate || null,
    });
  };

  return (
    <form onSubmit={submit} className="flex-col gap-3">
      <div className="field">
        <label>Description</label>
        <input className="input" value={desc} onChange={(e) => setDesc(e.target.value)} required placeholder="e.g. Rent, Software subscription" />
      </div>
      <div className="field-row">
        <div className="field">
          <label>Amount ($)</label>
          <input type="number" step="0.01" className="input" value={amount} onChange={(e) => setAmount(e.target.value)} required />
        </div>
        <div className="field">
          <label>Frequency</label>
          <select className="select" value={frequency} onChange={(e) => setFrequency(e.target.value as RecurringFrequency)}>
            {(Object.keys(FREQ_LABELS) as RecurringFrequency[]).map((f) => (
              <option key={f} value={f}>{FREQ_LABELS[f]}</option>
            ))}
          </select>
        </div>
      </div>
      {(frequency === 'monthly' || frequency === 'quarterly' || frequency === 'annually') && (
        <div className="field">
          <label>Day of month</label>
          <input type="number" className="input" min={1} max={28} value={dayOfMonth} onChange={(e) => setDayOfMonth(e.target.value)} />
        </div>
      )}
      <div className="field-row">
        <div className="field">
          <label>Start date</label>
          <input type="date" className="input" value={startDate} onChange={(e) => setStartDate(e.target.value)} required />
        </div>
        <div className="field">
          <label>End date (optional)</label>
          <input type="date" className="input" value={endDate} onChange={(e) => setEndDate(e.target.value)} />
        </div>
      </div>
      <div className="field-row">
        <div className="field">
          <label>Category</label>
          <input className="input" value={category} onChange={(e) => setCategory(e.target.value)} placeholder="optional" />
        </div>
        <div className="field">
          <label>&nbsp;</label>
          <label className="checkbox">
            <input type="checkbox" checked={deductible} onChange={(e) => setDeductible(e.target.checked)} />
            Tax deductible
          </label>
        </div>
      </div>
      <div className="modal-footer">
        <button type="button" className="btn" onClick={onCancel}>Cancel</button>
        <button type="submit" className="btn btn-primary">Save</button>
      </div>
    </form>
  );
}

// ─── Period summary strip (configurable tiles) ───────────────────────────────

const LEDGER_TILE_LABELS: Record<LedgerTile, string> = {
  ytd: 'YTD total',
  avgMonth: 'Avg / month',
  yearProj: 'Year projected',
  thisMonth: 'This month',
  avgDay: 'YTD daily avg',
  monthProj: 'Month projected',
  today: 'Today',
};

const ALL_LEDGER_TILES: LedgerTile[] = ['ytd', 'avgMonth', 'yearProj', 'thisMonth', 'avgDay', 'monthProj', 'today'];

const METRIC_COLOR: Record<'workValue' | 'payments' | 'expenses', string> = {
  workValue: 'positive',
  payments: 'positive',
  expenses: 'negative',
};

function PeriodSummaryRow({
  stats,
  metric,
  label,
  tiles,
  onConfigure,
}: {
  stats: ReturnType<typeof aggregate>;
  metric: 'workValue' | 'payments' | 'expenses';
  label: string;
  tiles: LedgerTile[];
  onConfigure: () => void;
}) {
  const { year: nowYear, monthIdx, day: nowDay, isoDate: today, isoMonth: currentMonth } = nowInTZ();
  const currentYear = String(nowYear);

  const y = stats.years.find((x) => x.label === currentYear);
  const m = stats.months.get(currentMonth);
  const d = stats.days.get(today);

  const yValue = y?.[metric] ?? 0;
  const mValue = m?.[metric] ?? 0;

  const monthsElapsed = monthIdx + 1;
  const dayOfMonth = nowDay;
  const daysInMonth = new Date(nowYear, monthIdx + 1, 0).getDate();
  // Days elapsed since Jan 1 inclusive, using noon-UTC to avoid DST drift
  const jan1Noon = Date.parse(`${nowYear}-01-01T12:00:00Z`);
  const todayNoon = Date.parse(`${today}T12:00:00Z`);
  const daysElapsed = Math.max(1, Math.floor((todayNoon - jan1Noon) / 86400000) + 1);
  const daysInYear = (nowYear % 4 === 0 && (nowYear % 100 !== 0 || nowYear % 400 === 0)) ? 366 : 365;

  const ytdDailyAvg = yValue / daysElapsed;

  const tileValues: Record<LedgerTile, number | null> = {
    ytd: yValue,
    avgMonth: yValue > 0 ? yValue / monthsElapsed : null,
    yearProj: yValue > 0 ? ytdDailyAvg * daysInYear : null,
    thisMonth: mValue,
    avgDay: yValue > 0 ? ytdDailyAvg : null,
    monthProj: mValue > 0 && dayOfMonth > 0 && dayOfMonth < daysInMonth
      ? (mValue / dayOfMonth) * daysInMonth
      : null,
    today: d?.[metric] ?? 0,
  };

  const tileDisplayLabel: Record<LedgerTile, string> = {
    ...LEDGER_TILE_LABELS,
    ytd: `YTD ${label}`,
  };

  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'flex-end', marginBottom: 4 }}>
        <button className="btn btn-sm btn-ghost" onClick={onConfigure}>⚙ Tiles</button>
      </div>
      <div className="stat-grid">
        {tiles.map((t) => {
          const value = tileValues[t];
          if (value == null) return null;
          return <StatTile key={t} label={tileDisplayLabel[t]} value={value} className={METRIC_COLOR[metric]} />;
        })}
      </div>
    </div>
  );
}

function StatTile({ label, value, className = '' }: { label: string; value: number; className?: string }) {
  return (
    <div className={`stat-card ${className}`}>
      <div className="stat-label">{label}</div>
      <div className="stat-value">{fmtMoney(value)}</div>
    </div>
  );
}

// ─── Tile configure modal (shared by all ledger tabs) ────────────────────────

function TileConfigModal({
  open,
  tiles,
  onChange,
  onClose,
}: {
  open: boolean;
  tiles: LedgerTile[];
  onChange: (tiles: LedgerTile[]) => void;
  onClose: () => void;
}) {
  const toggle = (t: LedgerTile) => {
    onChange(tiles.includes(t) ? tiles.filter((x) => x !== t) : [...tiles, t]);
  };
  return (
    <Modal open={open} title="Configure tiles" onClose={onClose} footer={
      <button className="btn btn-primary" onClick={onClose}>Done</button>
    }>
      <div className="flex-col gap-2">
        <p className="text-sm text-muted">Choose which tiles to display:</p>
        {ALL_LEDGER_TILES.map((t) => (
          <label key={t} className="checkbox">
            <input type="checkbox" checked={tiles.includes(t)} onChange={() => toggle(t)} />
            {LEDGER_TILE_LABELS[t]}
          </label>
        ))}
      </div>
    </Modal>
  );
}
