/* === Expenses + Fixed costs + Income screens === */

function ExpensesScreen({ state, setState, setOpenModal, setEditingExpense }) {
  const onEdit = (e) => {
    if (!setEditingExpense) return;
    setEditingExpense(e);
    setOpenModal('expense');
  };
  const { expenses, tags, family, activeMonth } = state;
  const [search, setSearch] = React.useState('');
  const [activeTags, setActiveTags] = React.useState([]);
  const [activeMembers, setActiveMembers] = React.useState([]);
  const [activeMerchants, setActiveMerchants] = React.useState([]);
  const [merchantSearch, setMerchantSearch] = React.useState('');
  const [sortBy, setSortBy] = React.useState('date'); // date | amount

  // Unique merchant list (current month) with totals
  const merchantList = React.useMemo(() => {
    const map = new Map();
    expenses.forEach(e => {
      const key = e.merchant;
      if (!map.has(key)) map.set(key, { merchant: key, total: 0, count: 0 });
      const entry = map.get(key);
      entry.total += e.amount;
      entry.count += 1;
    });
    return [...map.values()].sort((a, b) => b.total - a.total);
  }, [expenses]);

  const visibleMerchants = merchantSearch
    ? merchantList.filter(m => m.merchant.toLowerCase().includes(merchantSearch.toLowerCase()))
    : merchantList;

  let filtered = [...expenses];
  if (search) filtered = filtered.filter(e =>
    e.merchant.toLowerCase().includes(search.toLowerCase()) ||
    (e.note || '').toLowerCase().includes(search.toLowerCase())
  );
  if (activeTags.length) filtered = filtered.filter(e => activeTags.includes(e.tagId));
  if (activeMembers.length) filtered = filtered.filter(e => activeMembers.includes(e.memberId));
  if (activeMerchants.length) filtered = filtered.filter(e => activeMerchants.includes(e.merchant));

  if (sortBy === 'amount') filtered.sort((a, b) => b.amount - a.amount);
  else filtered.sort((a, b) => b.date.localeCompare(a.date));

  const total = filtered.reduce((s, e) => s + e.amount, 0);
  const monthTotal = expenses.reduce((s, e) => s + e.amount, 0);
  const avg = filtered.length ? total / filtered.length : 0;
  const filterActive = activeTags.length || activeMembers.length || activeMerchants.length || search;

  // Group by date
  const groups = {};
  if (sortBy === 'date') filtered.forEach(e => { (groups[e.date] = groups[e.date] || []).push(e); });

  const toggleIn = (arr, setter, id) => setter(arr.includes(id) ? arr.filter(x => x !== id) : [...arr, id]);
  const clearAll = () => { setActiveTags([]); setActiveMembers([]); setActiveMerchants([]); setSearch(''); setMerchantSearch(''); };

  // Per-tag totals (filter excluded for this dimension to keep numbers stable)
  const totalByTag = {};
  expenses.forEach(e => { totalByTag[e.tagId] = (totalByTag[e.tagId] || 0) + e.amount; });
  const totalByMember = {};
  expenses.forEach(e => { totalByMember[e.memberId] = (totalByMember[e.memberId] || 0) + e.amount; });

  return (
    <>
      <div className="page-head">
        <div>
          <div className="page-sub"><span className="hide-mobile">{formatMonthKey(activeMonth)} · </span>{filtered.length} of {expenses.length} transactions · {fmt(total, { cents: false })}{filterActive ? ` of ${fmt(monthTotal, { cents: false })}` : ''}</div>
          <h1 className="page-title">Expenses</h1>
        </div>
        <div className="row gap-sm">
          <button className="btn" onClick={() => setOpenModal('expense')}>+ New <span className="kbd">⌘N</span></button>
        </div>
      </div>

      <div className="expenses-layout">
        {/* Sidebar filter rail */}
        <aside className="filter-rail">
          <div className="filter-rail-head">
            <span className="eyebrow">Filters</span>
            {filterActive ? <button className="link-btn" onClick={clearAll}>Clear</button> : <span className="muted mono" style={{ fontSize: 10 }}>none</span>}
          </div>

          <input
            className="search-input"
            placeholder="Search merchants, notes…"
            value={search}
            onChange={e => setSearch(e.target.value)}
          />

          <div className="filter-totals">
            <div className="ft-row">
              <span className="ft-label">Showing</span>
              <span className="num ft-val">{fmt(total, { cents: false })}</span>
            </div>
            <div className="ft-row sub">
              <span className="ft-label">Avg / txn</span>
              <span className="num ft-val">{fmt(avg, { cents: false })}</span>
            </div>
            <div className="ft-row sub">
              <span className="ft-label">Count</span>
              <span className="num ft-val">{filtered.length}</span>
            </div>
          </div>

          {/* Members */}
          <div className="filter-group-head">
            <span className="eyebrow">Family</span>
            {activeMembers.length > 0 && <button className="link-btn" onClick={() => setActiveMembers([])}>reset</button>}
          </div>
          <div className="filter-list">
            {family.map(m => {
              const t = totalByMember[m.id] || 0;
              const active = activeMembers.includes(m.id);
              return (
                <button key={m.id}
                  className={`filter-row ${active ? 'active' : ''}`}
                  onClick={() => toggleIn(activeMembers, setActiveMembers, m.id)}>
                  <span className="member-chip mini" style={{ background: TAG_COLORS[m.color] }}>{nameInitials(m.name)}</span>
                  <span className="fr-label">{m.name}</span>
                  <span className="num fr-val">{fmt(t, { cents: false })}</span>
                </button>
              );
            })}
          </div>

          {/* Tags */}
          <div className="filter-group-head">
            <span className="eyebrow">Tags</span>
            {activeTags.length > 0 && <button className="link-btn" onClick={() => setActiveTags([])}>reset</button>}
          </div>
          <div className="filter-list">
            {tags.map(t => {
              const v = totalByTag[t.id] || 0;
              const active = activeTags.includes(t.id);
              return (
                <button key={t.id}
                  className={`filter-row ${active ? 'active' : ''}`}
                  onClick={() => toggleIn(activeTags, setActiveTags, t.id)}>
                  <span className="dot" style={{ background: TAG_COLORS[t.color] }} />
                  <span className="fr-label">{t.name}</span>
                  <span className="num fr-val">{fmt(v, { cents: false })}</span>
                </button>
              );
            })}
          </div>

          {/* Merchants */}
          <div className="filter-group-head">
            <span className="eyebrow">Merchants · {merchantList.length}</span>
            {activeMerchants.length > 0 && <button className="link-btn" onClick={() => setActiveMerchants([])}>reset</button>}
          </div>
          <input
            className="search-input small"
            placeholder="Filter list…"
            value={merchantSearch}
            onChange={e => setMerchantSearch(e.target.value)}
          />
          <div className="filter-list scroll">
            {visibleMerchants.map(m => {
              const active = activeMerchants.includes(m.merchant);
              return (
                <button key={m.merchant}
                  className={`filter-row ${active ? 'active' : ''}`}
                  onClick={() => toggleIn(activeMerchants, setActiveMerchants, m.merchant)}>
                  <span className="fr-count">{m.count}</span>
                  <span className="fr-label" title={m.merchant}>{m.merchant}</span>
                  <span className="num fr-val">{fmt(m.total, { cents: false })}</span>
                </button>
              );
            })}
            {visibleMerchants.length === 0 && (
              <div className="muted mono" style={{ fontSize: 10.5, padding: '8px 4px' }}>no matches</div>
            )}
          </div>
        </aside>

        {/* Transaction list */}
        <div className="expenses-list">
          <div className="list-toolbar">
            <span className="eyebrow">Sort</span>
            <button className={`seg ${sortBy === 'date' ? 'active' : ''}`} onClick={() => setSortBy('date')}>Date</button>
            <button className={`seg ${sortBy === 'amount' ? 'active' : ''}`} onClick={() => setSortBy('amount')}>Amount</button>
            <span style={{ flex: 1 }}></span>
            <span className="muted mono" style={{ fontSize: 10.5 }}>
              {filtered.length} {filtered.length === 1 ? 'item' : 'items'} · <span className="num">{fmt(total, { cents: false })}</span>
            </span>
          </div>

          {sortBy === 'date' ? (
            Object.entries(groups).map(([date, items]) => {
              const dayTotal = items.reduce((s, e) => s + e.amount, 0);
              return (
                <div key={date} className="day-group by-date">
                  <div className="between" style={{ paddingBottom: 8, borderBottom: '0.5px solid var(--rule)' }}>
                    <span className="eyebrow">{monthDay(date)} · {new Date(date + 'T00:00:00').toLocaleDateString('en', { weekday: 'long' })}</span>
                    <span className="num muted" style={{ fontSize: 11 }}>{fmt(dayTotal)}</span>
                  </div>
                  {items.map(e => <ExpenseRow key={e.id} e={e} state={state} setState={setState} onEdit={onEdit} />)}
                </div>
              );
            })
          ) : (
            <div className="day-group" style={{ marginTop: 12 }}>
              {filtered.map(e => <ExpenseRow key={e.id} e={e} state={state} setState={setState} onEdit={onEdit} />)}
            </div>
          )}

          {filtered.length === 0 && (
            <div style={{ textAlign: 'center', padding: 60, color: 'var(--ink-3)' }}>
              <div className="eyebrow">No matches</div>
              {filterActive && <button className="btn ghost" style={{ marginTop: 12 }} onClick={clearAll}>Clear filters</button>}
            </div>
          )}
        </div>
      </div>
    </>
  );
}

function ExpenseRow({ e, state, setState, onEdit }) {
  const { tags, family } = state;
  const t = tagById(tags, e.tagId);
  const m = e.memberId ? memberById(family, e.memberId) : null;
  return (
    <div className="txn">
      <div className="txn-date">{monthDay(e.date)}</div>
      <div>
        <div className="txn-merchant">{e.merchant}</div>
        <div className="txn-meta">
          <Tag tag={t} />
          {m && (
            <span className="member-chip mini" style={{ background: TAG_COLORS[m.color] }} title={m.name}>{nameInitials(m.name)}</span>
          )}
          {e.note && <span className="muted">· {e.note}</span>}
        </div>
      </div>
      <div className="row gap-sm" style={{ alignItems: 'center' }}>
        {onEdit && (
          <button className="btn ghost" style={{ height: 22, fontSize: 11, padding: '0 8px' }}
            onClick={() => onEdit(e)}>
            edit
          </button>
        )}
        <button className="btn ghost" style={{ height: 22, fontSize: 11, padding: '0 8px' }}
          onClick={() => setState(s => ({ ...s, expenses: s.expenses.filter(x => x.id !== e.id) }))}>
          delete
        </button>
      </div>
      <div className="txn-amount expense num">{e.amount.toFixed(2)}</div>
    </div>
  );
}

const DAY_NAMES_SHORT = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];

const fixedDueLabel = (f) => {
  const freq = f.frequency || 'monthly';
  if (freq === 'weekly') return DAY_NAMES_SHORT[(parseInt(f.due) || 0) % 7];
  if (freq === 'yearly') return `${MONTH_SHORT[(parseInt(f.dueMonth) || 1) - 1]} ${f.due || 1}`;
  return String(f.due || 1);
};

const fixedFrequencyLabel = (f) => {
  const freq = f.frequency || 'monthly';
  if (freq === 'weekly') return `every ${['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'][(parseInt(f.due) || 0) % 7]}`;
  if (freq === 'yearly') return `every ${MONTH_NAMES[(parseInt(f.dueMonth) || 1) - 1]} ${f.due || 1}`;
  return 'every month';
};

const FREQ_ORDER = { monthly: 0, weekly: 1, yearly: 2 };

function FixedScreen({ state, setState, setOpenModal }) {
  const { fixed, tags } = state;
  const totalMonthly = fixed.reduce((s, f) => s + monthlyEquiv(f), 0);
  const sorted = [...fixed].sort((a, b) => {
    const fa = FREQ_ORDER[a.frequency || 'monthly'];
    const fb = FREQ_ORDER[b.frequency || 'monthly'];
    if (fa !== fb) return fa - fb;
    return (a.due || 0) - (b.due || 0);
  });

  return (
    <>
      <div className="page-head">
        <div>
          <div className="page-sub">{fixed.length} recurring · {fmt(totalMonthly, { cents: false })}/mo equivalent</div>
          <h1 className="page-title">Fixed costs</h1>
        </div>
        <button className="btn" onClick={() => setOpenModal('fixed')}>+ Add recurring</button>
      </div>

      <div style={{ padding: '20px 28px 28px' }}>
        <div className="card list-card">
          <div className="card-section">
            Schedule
            <span className="eyebrow num">due</span>
          </div>
          {sorted.map(f => {
            const t = tagById(tags, f.tagId);
            const freq = f.frequency || 'monthly';
            const suffix = freq === 'weekly' ? '/wk' : freq === 'yearly' ? '/yr' : '/mo';
            return (
              <div key={f.id} className="txn fixed-row" style={{ gridTemplateColumns: '64px 1fr auto auto' }}>
                <div className="txn-date" style={{ fontSize: 13, color: 'var(--ink)' }}>{fixedDueLabel(f)}</div>
                <div>
                  <div className="txn-merchant">{f.name}</div>
                  <div className="txn-meta">
                    <Tag tag={t} />
                    <span className="muted">· {fixedFrequencyLabel(f)}</span>
                  </div>
                </div>
                <button className="btn ghost" style={{ height: 22, fontSize: 11, padding: '0 8px' }}
                  onClick={() => setState(s => ({ ...s, fixed: s.fixed.filter(x => x.id !== f.id) }))}>
                  remove
                </button>
                <div className="txn-amount expense num">
                  {f.amount.toFixed(2)}
                  <span className="muted" style={{ fontSize: 10, marginLeft: 4 }}>{suffix}</span>
                </div>
              </div>
            );
          })}
          <div className="txn" style={{ gridTemplateColumns: '64px 1fr auto auto', borderTop: '1px solid var(--ink)', borderBottom: 'none', marginTop: 6, paddingTop: 12 }}>
            <div></div>
            <div className="txn-merchant" style={{ fontWeight: 600 }}>Total monthly equivalent</div>
            <div></div>
            <div className="txn-amount expense num" style={{ fontSize: 15, fontWeight: 600 }}>{totalMonthly.toFixed(2)}</div>
          </div>
        </div>
      </div>
    </>
  );
}

function IncomeScreen({ state, setState, setOpenModal }) {
  const { extra, family, activeMonth } = state;
  const [income, setIncome] = React.useState(state.income);
  const [label, setLabel] = React.useState(state.incomeLabel);

  const save = () => setState(s => ({ ...s, income: parseFloat(income) || 0, incomeLabel: label }));

  const sortedExtra = [...(extra || [])].sort((a, b) => b.date.localeCompare(a.date));
  const extraTotal = sortedExtra.reduce((s, x) => s + x.amount, 0);
  const totalThisMonth = (parseFloat(income) || 0) + extraTotal;
  const removeExtra = (id) => setState(s => ({ ...s, extra: (s.extra || []).filter(x => x.id !== id) }));

  return (
    <>
      <div className="page-head">
        <div>
          <div className="page-sub">{formatMonthKey(activeMonth)} · {fmt(totalThisMonth, { cents: false })} total inflow</div>
          <h1 className="page-title">Income</h1>
        </div>
        <button className="btn primary" onClick={() => setOpenModal('extra')}>+ Extra income</button>
      </div>
      <div style={{ padding: '24px 28px 28px', display: 'grid', gridTemplateColumns: 'minmax(0, 480px) 1fr', gap: 22, alignItems: 'start' }}>
        <div className="card">
          <div className="card-section">Primary income</div>
          <div className="field" style={{ marginBottom: 18 }}>
            <span className="field-label">Source</span>
            <input className="input" value={label} onChange={e => setLabel(e.target.value)} />
          </div>
          <div className="field">
            <span className="field-label">Monthly amount (after tax)</span>
            <div className="amount-wrap">
              <input
                className="input amount"
                type="number"
                step="0.01"
                value={income}
                onChange={e => setIncome(e.target.value)}
              />
            </div>
          </div>
          <div className="divider" />
          <div className="between">
            <span className="eyebrow">Annualized</span>
            <span className="num" style={{ fontSize: 14 }}>{fmt(parseFloat(income) * 12 || 0, { cents: false })}</span>
          </div>
          <div className="between" style={{ marginTop: 8 }}>
            <span className="eyebrow">Weekly equivalent</span>
            <span className="num" style={{ fontSize: 14 }}>{fmt((parseFloat(income) || 0) * 12 / 52, { cents: false })}</span>
          </div>
          <div style={{ marginTop: 18, display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
            <button className="btn primary" onClick={save}>Save changes</button>
          </div>
        </div>

        <div className="card list-card">
          <div className="card-section">
            Extra income · {formatMonthKeyShort(activeMonth)}
            <span className="num" style={{ color: 'var(--pos)', fontSize: 13 }}>+{fmt(extraTotal, { cents: false })}</span>
          </div>
          <div className="muted mono" style={{ fontSize: 11, lineHeight: 1.6, marginBottom: 10 }}>
            Side income, freelance, gifts, refunds — anything that lands outside your primary salary. Counts toward this month's available cash.
          </div>
          {sortedExtra.length === 0 ? (
            <div style={{ textAlign: 'center', padding: '28px 12px', color: 'var(--ink-3)' }}>
              <div className="eyebrow" style={{ marginBottom: 10 }}>No extra income this month</div>
              <button className="btn" onClick={() => setOpenModal('extra')}>+ Log your first</button>
            </div>
          ) : (
            sortedExtra.map(x => {
              const m = memberById(family, x.memberId);
              return (
                <div key={x.id} className="txn">
                  <div className="txn-date">{monthDay(x.date)}</div>
                  <div>
                    <div className="txn-merchant">{x.source}</div>
                    <div className="txn-meta">
                      <span className="member-chip mini" style={{ background: TAG_COLORS[m.color] }} title={m.name}>{nameInitials(m.name)}</span>
                      <span className="muted" style={{ color: 'var(--ink-3)' }}>· {m.name}</span>
                      {x.note && <span className="muted">· {x.note}</span>}
                    </div>
                  </div>
                  <button className="btn ghost" style={{ height: 22, fontSize: 11, padding: '0 8px' }}
                    onClick={() => removeExtra(x.id)}>delete</button>
                  <div className="txn-amount num" style={{ color: 'var(--pos)' }}>+{x.amount.toFixed(2)}</div>
                </div>
              );
            })
          )}
          {sortedExtra.length > 0 && (
            <div className="txn" style={{ gridTemplateColumns: '40px 1fr auto auto', borderTop: '1px solid var(--ink)', borderBottom: 'none', marginTop: 6, paddingTop: 12 }}>
              <div></div>
              <div className="txn-merchant" style={{ fontWeight: 600 }}>Total extra · {formatMonthKeyShort(activeMonth)}</div>
              <div></div>
              <div className="txn-amount num" style={{ fontSize: 15, fontWeight: 600, color: 'var(--pos)' }}>+{extraTotal.toFixed(2)}</div>
            </div>
          )}
        </div>
      </div>

      <div style={{ padding: '0 28px 28px', maxWidth: 1100 }}>
        <div className="card" style={{ background: 'transparent', borderStyle: 'dashed' }}>
          <div className="between">
            <div>
              <div className="eyebrow" style={{ marginBottom: 4 }}>Available this month</div>
              <div className="num" style={{ fontFamily: 'var(--font-display)', fontSize: 28, color: 'var(--ink)', letterSpacing: '-0.02em' }}>
                {fmt(totalThisMonth, { cents: false })}
              </div>
            </div>
            <div style={{ textAlign: 'right' }}>
              <div className="muted mono" style={{ fontSize: 11 }}>
                {fmt(parseFloat(income) || 0, { cents: false })} salary
                {extraTotal > 0 && <> · <span style={{ color: 'var(--pos)' }}>+{fmt(extraTotal, { cents: false })} extra</span></>}
              </div>
            </div>
          </div>
        </div>
      </div>
    </>
  );
}

Object.assign(window, { ExpensesScreen, FixedScreen, IncomeScreen, ExpenseRow });
