// Banking — bank & credit-card statements detected from the inbox, grouped by institution.
// Collapsible groups, status + account-type filters, search, statement detail drawer,
// "Connect account" create flow, and paginated institution list.

const ST_META = {
  new:      { cls:'b-blue',  label:'New' },
  reviewed: { cls:'b-gray',  label:'Filed' },
  paid:     { cls:'b-green', label:'Paid' },
  due:      { cls:'b-gold',  label:'Due' },
  overdue:  { cls:'b-red',   label:'Overdue' },
};
const PER_PAGE = 4;

function typeMeta(types, id) { return types.find(t => t.id === id) || { label: id, tint: 'gold', icon: 'landmark' }; }

// A statement may carry more than one file (e.g. the PDF statement + a
// transactions CSV + a tax summary). Fall back to a single derived PDF.
const stmtFiles = s => (s.files && s.files.length) ? s.files
  : [{ name: `${s.period.replace(/[^\w]+/g, '-')}.pdf`, kind:'PDF', pages: s.pages }];
const fileIc = f => { const k = (f.kind || '').toLowerCase(); return k === 'csv' ? 'file-spreadsheet' : k === 'pdf' ? 'file-text' : 'file'; };
const fmtKB = b => !b ? '' : b >= 1048576 ? (b / 1048576).toFixed(1) + ' MB' : Math.max(1, Math.round(b / 1024)) + ' KB';

const BANK_MON = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
const bankDate = iso => { const d = new Date(iso); return isNaN(d) ? '' : `${BANK_MON[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}`; };
const emailSubject = (inst, stmt) => `${inst.name} — statement for ${stmt.period}`;

// Open a tasteful preview of the exact email a record was detected from, so the
// user can trace any statement back to its source (and see which inbox caught it).
function openSourceEmail(inst, stmt) {
  const from = inst.sender || 'statements@bank.com';
  const subject = emailSubject(inst, stmt);
  const received = bankDate(stmt.periodISO);
  const mailbox = inst.mailbox || 'you@gmail.com';
  const initial = (inst.name || '?').trim()[0].toUpperCase();
  const atts = stmtFiles(stmt).map(f =>
    `<div class="att"><span class="ai">${(f.kind||'FILE')}</span><span class="an">${f.name}</span><span class="ad">${f.pages?f.pages+' pages':''}</span></div>`).join('');
  const html = `<!doctype html><html><head><meta charset="utf-8"><title>${subject}</title>
  <style>
    *{box-sizing:border-box} body{margin:0;background:#ECEAE5;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;color:#1c1b20;padding:28px}
    .mail{max-width:680px;margin:0 auto;background:#fff;border:1px solid #E4E1DB;border-radius:14px;overflow:hidden;box-shadow:0 18px 48px rgba(40,30,12,.12)}
    .mbar{display:flex;align-items:center;gap:8px;padding:10px 18px;background:#FBF7EE;border-bottom:1px solid #EEE7D6;font-size:12px;color:#8A6529;font-weight:600}
    .mbar .dot{width:7px;height:7px;border-radius:50%;background:#C19A4B}
    .hd{display:flex;gap:14px;align-items:flex-start;padding:22px 24px 18px;border-bottom:1px solid #EFEDE8}
    .av{width:46px;height:46px;border-radius:12px;flex:none;display:grid;place-items:center;background:#F1ECE0;color:#A8803A;font-weight:800;font-size:20px;font-family:Georgia,serif}
    .subj{font-size:19px;font-weight:700;line-height:1.3;margin:0 0 6px}
    .from{font-size:13.5px;color:#5C5B61}.from b{color:#1c1b20}
    .when{font-size:12.5px;color:#8A8A90;margin-top:3px}
    .bd{padding:22px 24px;font-size:14.5px;line-height:1.65;color:#3a3942}
    .bd p{margin:0 0 14px}
    .atts{padding:4px 24px 24px}.atts h4{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:#8A8A90;margin:0 0 10px}
    .att{display:flex;align-items:center;gap:12px;border:1px solid #E4E1DB;border-radius:10px;padding:11px 13px;margin-bottom:8px}
    .att .ai{font:700 10px/1 -apple-system;letter-spacing:.05em;color:#A8803A;background:#FBF7EE;border:1px solid #EAE1CC;border-radius:6px;padding:6px 7px}
    .att .an{flex:1;font-size:13.5px;font-weight:600;color:#1c1b20}.att .ad{font-size:12px;color:#8A8A90}
    .ft{padding:14px 24px;border-top:1px solid #EFEDE8;font-size:11.5px;color:#ACACB1}
  </style></head><body>
    <div class="mail">
      <div class="mbar"><span class="dot"></span> Detected by Zeranda · from ${mailbox}</div>
      <div class="hd"><div class="av">${initial}</div>
        <div><div class="subj">${subject}</div>
          <div class="from"><b>${inst.name}</b> &lt;${from}&gt;</div>
          <div class="from">to ${mailbox}</div>
          <div class="when">${received}</div>
        </div></div>
      <div class="bd"><p>Dear Customer,</p>
        <p>Please find attached your account statement for <b>${stmt.period}</b> for ${inst.name} account ${inst.account}. Your ${stmt.amountLabel.toLowerCase()} is <b>${stmt.amount}</b>.</p>
        <p>This is a system-generated email. Please do not reply.</p></div>
      <div class="atts"><h4>${stmtFiles(stmt).length} attachment${stmtFiles(stmt).length===1?'':'s'}</h4>${atts}</div>
      <div class="ft">Source email preview · not available to send or forward in this demo.</div>
    </div>
  </body></html>`;
  window.open(URL.createObjectURL(new Blob([html], { type:'text/html' })), '_blank');
}
// ---- Convert a statement into another record type ----
// A statement detected from the inbox isn't always an account statement: it may
// really be a payment receipt, or a credit-card bill that has to be paid. These
// builders turn the same record into a Receipt or a Bill object so it can be
// MOVED into those sections — the statement leaves Banking and lands there.
const RC_MONTHS = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
const isoToShort = iso => { if (!iso) return ''; const d = new Date(iso); return isNaN(d) ? '' : `${RC_MONTHS[d.getMonth()]} ${d.getDate()}`; };
const convRef = stmt => ((stmt.id || 'tx').toUpperCase() + '-' + (stmt.periodISO || '').replace(/-/g, '')).replace(/[^A-Z0-9-]/g, '');
const filesToAttachments = stmt => (stmtFiles(stmt) || []).map((f, n) => ({ id: (stmt.id || 'st') + '-a' + n, name: f.name, size: f.size }));

// Statement -> Receipt (a payment/confirmation record filed under Receipts).
function statementToReceipt(inst, stmt, tm) {
  const settled = stmt.status === 'paid' || stmt.status === 'reviewed';
  return {
    id: 'r-' + (stmt.id || Date.now()),
    merchant: inst.name,
    icon: inst.icon,
    tint: tm.tint || 'teal',
    detail: `${stmt.amountLabel} · ${stmt.period}`,
    order: convRef(stmt),
    items: [{ label: stmt.amountLabel, amt: stmt.amountVal }],
    ccy: 'USD',
    amountVal: stmt.amountVal,
    date: isoToShort(stmt.periodISO),
    dateISO: stmt.periodISO || new Date().toISOString().slice(0, 10),
    cat: 'Banking',
    type: settled ? 'purchase' : 'statement',
    source: true,
    mailbox: inst.mailbox,
    sender: inst.sender,
    attachments: filesToAttachments(stmt),
    convertedFrom: { kind: 'statement', inst: inst.name, account: inst.account, mailbox: inst.mailbox },
  };
}

// Statement -> Bill (a payable, filed under Bills with a due date).
function statementToBill(inst, stmt, tm) {
  const status = stmt.status === 'paid' ? 'paid' : stmt.status === 'overdue' ? 'overdue' : 'pending';
  return {
    id: 'b-' + (stmt.id || Date.now()),
    merchant: inst.name,
    cat: 'Banking',
    catId: 'banking',
    catTint: tm.tint || 'gold',
    icon: inst.icon,
    ccy: 'USD',
    amountVal: stmt.amountVal,
    due: stmt.due || isoToShort(stmt.periodISO),
    dueISO: stmt.periodISO || new Date().toISOString().slice(0, 10),
    status,
    account: inst.account,
    confidence: 95,
    mailbox: inst.mailbox,
    sender: inst.sender,
    items: [{ label: stmt.amountLabel, amt: stmt.amountVal }],
    attachments: filesToAttachments(stmt),
    convertedFrom: { kind: 'statement', inst: inst.name, account: inst.account, mailbox: inst.mailbox },
  };
}

function fileSummary(files) {
  if (files.length === 1) { const f = files[0]; return `${f.pages ? f.pages + '-page ' : ''}${f.kind || 'file'}`; }
  const kinds = [...new Set(files.map(f => f.kind).filter(Boolean))].join(', ');
  return `${files.length} files${kinds ? ' · ' + kinds : ''}`;
}

// Row download control — direct download for one file, a popover picker for many.
function StmtAttach({ files }) {
  const [open, setOpen] = useState(false);
  const [pos, setPos] = useState(null);
  const btnRef = useRef(null);
  useEffect(() => {
    if (!open) return;
    const close = () => setOpen(false);
    const onKey = e => { if (e.key === 'Escape') setOpen(false); };
    window.addEventListener('scroll', close, true);
    window.addEventListener('resize', close);
    document.addEventListener('keydown', onKey);
    return () => { window.removeEventListener('scroll', close, true); window.removeEventListener('resize', close); document.removeEventListener('keydown', onKey); };
  }, [open]);

  if (files.length === 1)
    return <button className="iconbtn" title={`Download ${files[0].name}`} onClick={e => { e.stopPropagation(); openAttachment(files[0]); }}><Icon name="download" size={16} /></button>;

  const toggle = e => {
    e.stopPropagation();
    if (open) { setOpen(false); return; }
    const r = btnRef.current.getBoundingClientRect();
    const right = Math.max(12, window.innerWidth - r.right);
    const estH = 54 + files.length * 44 + 42;           // header + rows + "download all"
    const spaceBelow = window.innerHeight - r.bottom;
    const openUp = spaceBelow < estH + 16 && r.top > spaceBelow;   // flip up when cramped below
    setPos(openUp ? { right, bottom: window.innerHeight - r.top + 8 } : { right, top: r.bottom + 8 });
    setOpen(true);
  };
  const pick = f => { openAttachment(f); setOpen(false); };
  return (
    <React.Fragment>
      <button ref={btnRef} className={`iconbtn att-btn ${open ? 'on' : ''}`} title={`${files.length} attachments`} onClick={toggle}>
        <Icon name="paperclip" size={16} /><span className="att-n">{files.length}</span>
      </button>
      {open && pos && ReactDOM.createPortal(
        <React.Fragment>
          <div className="att-pop-scrim" onClick={e => { e.stopPropagation(); setOpen(false); }} />
          <div className="att-pop" style={{ top: pos.top, bottom: pos.bottom, right: pos.right }} onClick={e => e.stopPropagation()}>
            <div className="att-pop-h">{files.length} attachments · pick one to open</div>
            {files.map(f => (
              <button className="att-pop-row" key={f.name} onClick={() => pick(f)}>
                <Icon name={fileIc(f)} size={16} color="var(--fg-3)" />
                <span className="ap-name">{f.name}</span>
                <span className="ap-meta">{f.pages ? `${f.pages}p` : ''}{f.pages && f.size ? ' · ' : ''}{fmtKB(f.size)}</span>
                <Icon name="download" size={14} color="var(--fg-4)" />
              </button>
            ))}
            <button className="att-pop-all" onClick={() => { files.forEach(openAttachment); setOpen(false); }}><Icon name="download" size={14} /> Download all</button>
          </div>
        </React.Fragment>,
        document.body
      )}
    </React.Fragment>
  );
}

// ---- Statement detail drawer (view + quick actions) ----
function StatementDrawer({ inst, stmt, typeMetaFn, onClose, onStatus, onDelete, onConvert }) {
  const tm = typeMetaFn(inst.type);
  const m = ST_META[stmt.status];
  const files = stmtFiles(stmt);
  // A detected "statement" is sometimes really a payment receipt, or a
  // credit-card bill that has to be paid. Suggest the right destination from
  // the amount label, but let the user move it either way.
  const suggested = /due|payable|emi|minimum/i.test(stmt.amountLabel || '') ? 'bill'
    : /paid|received|refund/i.test(stmt.amountLabel || '') ? 'receipt' : null;
  const [dest, setDest] = useState(suggested || 'receipt');
  const DEST = {
    receipt: { note: 'Move this out of Banking and file it under Receipts as a payment record — for when the email is really a confirmation, not a statement.', label: 'Move to Receipts', icon: 'receipt' },
    bill:    { note: 'Move this out of Banking and file it under Bills as a payable, with its amount and due date — useful for credit-card statements you need to pay.', label: 'Move to Bills', icon: 'dollar-sign' },
  };
  const d = DEST[dest];
  // A record can't be filed without a figure — Receipts and Bills both key off
  // the amount. If the detected statement has none, intercept the move and ask
  // for it inline, then complete the move with the value the user enters.
  const hasAmount = stmt.amountVal != null && stmt.amountVal !== '';
  const [asking, setAsking] = useState(false);
  const [amt, setAmt] = useState('');
  const [amtErr, setAmtErr] = useState('');
  const amtRef = useRef(null);
  useEffect(() => { if (asking && amtRef.current) amtRef.current.focus(); }, [asking]);
  const tryMove = () => {
    if (hasAmount) { onConvert(dest); return; }            // amount present — move straight away
    if (!asking) { setAsking(true); setAmtErr(''); return; } // no amount — reveal the inline prompt
    const n = parseFloat(amt.replace(/[^0-9.\-]/g, ''));
    if (!amt.trim() || !isFinite(n)) { setAmtErr('Enter an amount to file this record.'); return; }
    onConvert(dest, n);                                     // move with the amount the user added
  };
  return (
    <React.Fragment>
      <div className="scrim" onClick={onClose} />
      <div className="drawer zd-scroll">
        <div className="dhead">
          <IconChip icon={inst.icon} tint={tm.tint} size={40} radius={12} />
          <div style={{ flex:1, minWidth:0 }}>
            <div style={{ fontFamily:'var(--font-display)', fontWeight:700, fontSize:18, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{inst.name}</div>
            <div style={{ fontSize:12.5, color:'var(--fg-3)' }}>{tm.label} · {inst.account}</div>
          </div>
          <button className="iconbtn" onClick={onClose}><Icon name="x" size={18} /></button>
        </div>
        <div className="dbody">
          <div className="field"><div className="k">{stmt.amountLabel || 'Amount'}</div>{hasAmount
            ? <Money amount={stmt.amountVal} ccy="USD" align="left" size={30} primaryClass="zd-stat" />
            : <div className="v" style={{ display:'flex', alignItems:'center', gap:7, color:'var(--fg-4)', fontSize:15 }}><Icon name="alert-circle" size={15} color="var(--gold-600)" />No amount detected</div>}</div>
          <div className="drow">
            <div className="field" style={{ flex:1 }}><div className="k">Statement period</div><div className="v" style={{ fontSize:14.5 }}>{stmt.period}</div></div>
            <div className="field" style={{ flex:1 }}><div className="k">Status</div><div className="v"><span className={`badge ${m.cls}`}>{m.label}{stmt.due ? ` · ${stmt.due}` : ''}</span></div></div>
          </div>
          <div className="field"><div className="k">Account</div><div className="v zd-mono" style={{ fontSize:13.5 }}>{inst.account}</div></div>

          <div className="field"><div className="k">{files.length > 1 ? `Attachments · ${files.length}` : 'Attachment'}</div>
            <div className="att-list">
              {files.map(f => (
                <div className="att-row" key={f.name}>
                  <span className="att-ic"><Icon name={fileIc(f)} size={16} color="var(--fg-3)" /></span>
                  <div className="att-meta"><div className="an">{f.name}</div><div className="as">{f.pages ? `${f.pages}-page ` : ''}{f.kind}{f.size ? ` · ${fmtKB(f.size)}` : ''}</div></div>
                  <button className="iconbtn" title="View" onClick={() => openAttachment(f)}><Icon name="eye" size={16} /></button>
                  <button className="iconbtn" title="Download" onClick={() => openAttachment(f)}><Icon name="download" size={16} /></button>
                </div>
              ))}
            </div>
          </div>

          <div className="field"><div className="k">Source email</div>
            <button className="src-card" onClick={() => openSourceEmail(inst, stmt)} title="Open the email this was detected from">
              <span className="src-ic"><Icon name="mail" size={17} color="var(--gold-600)" /></span>
              <div className="src-body">
                <div className="src-subj">{emailSubject(inst, stmt)}</div>
                <div className="src-from">{inst.sender}</div>
                <div className="src-meta"><span className="src-mbx"><Icon name="inbox" size={12} /> {inst.mailbox}</span><span className="src-sep">·</span>{bankDate(stmt.periodISO)}</div>
              </div>
              <Icon name="external-link" size={15} color="var(--fg-4)" />
            </button>
          </div>
          <div className="field">
            <div className="k">Not a statement? Move it</div>
            <div className="seg-full" style={{ marginBottom: 10 }}>
              {[['receipt', 'Receipt', 'receipt'], ['bill', 'Bill', 'dollar-sign']].map(([id, lbl, ic]) => (
                <button key={id} className={dest === id ? 'on' : ''} onClick={() => setDest(id)}>
                  <Icon name={ic} size={15} />{lbl}{id === suggested ? <span className="badge b-gold" style={{ marginLeft: 2, padding: '1px 6px', fontSize: 9.5 }}>suggested</span> : null}
                </button>
              ))}
            </div>
            <div style={{ fontSize: 12.5, color: 'var(--fg-3)', lineHeight: 1.5, marginBottom: 12 }}>{d.note}</div>
            {asking && !hasAmount && (
              <div style={{ marginBottom: 12 }}>
                <div style={{ display:'flex', alignItems:'flex-start', gap:7, fontSize:12.5, fontWeight:600, color:'var(--fg-2)', marginBottom:8, lineHeight:1.45 }}>
                  <Icon name="alert-circle" size={15} color="var(--gold-600)" style={{ flex:'none', marginTop:1 }} />
                  <span>This statement has no amount. Add one to file it as a {dest === 'bill' ? 'bill' : 'receipt'}.</span>
                </div>
                <div className="finput" style={{ marginBottom: amtErr ? 6 : 0, borderColor: amtErr ? 'var(--red-500)' : undefined }}>
                  <span className="fpre">$</span>
                  <input ref={amtRef} inputMode="decimal" placeholder="0.00" value={amt}
                    onChange={e => { setAmt(e.target.value); if (amtErr) setAmtErr(''); }}
                    onKeyDown={e => { if (e.key === 'Enter') tryMove(); }} />
                </div>
                {amtErr && <div style={{ fontSize: 11.5, color: 'var(--red-600)' }}>{amtErr}</div>}
              </div>
            )}
            <button className="btn btn-secondary" style={{ width: '100%', justifyContent: 'center' }} onClick={tryMove}>
              <Icon name={asking && !hasAmount ? 'plus' : d.icon} size={16} />
              {asking && !hasAmount ? `Add amount & ${d.label.toLowerCase()}` : d.label}
              <Icon name="arrow-right" size={14} style={{ opacity: .55 }} />
            </button>
          </div>
          <div className="drawer-foot">
            <button className="btn btn-primary" style={{ flex:1, justifyContent:'center' }} onClick={() => files.forEach(openAttachment)}><Icon name="download" size={16} />{files.length > 1 ? `Download all (${files.length})` : 'Download PDF'}</button>
            {(stmt.status === 'due' || stmt.status === 'overdue')
              ? <Btn variant="secondary" icon="check" onClick={() => onStatus('paid')}>Mark paid</Btn>
              : stmt.status === 'new'
                ? <Btn variant="secondary" icon="check" onClick={() => onStatus('reviewed')}>Mark filed</Btn>
                : <Btn variant="secondary" icon="mail">Source</Btn>}
            <button className="iconbtn danger" onClick={onDelete} title="Delete"><Icon name="trash-2" size={17} /></button>
          </div>
        </div>
      </div>
    </React.Fragment>
  );
}

function Banking({ go }) {
  const D = window.ZD_DATA;
  const types = D.banking.accountTypes;
  const [insts, setInsts] = useState(D.banking.institutions);
  const [status, setStatus] = useState('all');   // all | due | new | filed
  const [type, setType] = useState('all');
  const [q, setQ] = useState('');
  const [page, setPage] = useState(1);
  const [collapsed, setCollapsed] = useState({});
  const [sel, setSel] = useState(null);           // { instId, stmtId }
  const [creating, setCreating] = useState(false);
  const [moved, setMoved] = useState(null);        // { dest, merchant } — convert confirmation
  useEffect(() => { if (!moved) return; const t = setTimeout(() => setMoved(null), 5000); return () => clearTimeout(t); }, [moved]);
  useCreateShortcut(() => setCreating(true));
  const tmFn = id => typeMeta(types, id);

  const all = insts.flatMap(i => i.statements);
  const counts = {
    all: all.length,
    due: all.filter(s => s.status === 'due' || s.status === 'overdue').length,
    new: all.filter(s => s.status === 'new').length,
    filed: all.filter(s => s.status === 'paid' || s.status === 'reviewed').length,
  };
  const dueTotal = all.filter(s => s.status === 'due' || s.status === 'overdue').reduce((a, s) => a + s.amountVal, 0);

  const matchStatus = s =>
    status === 'all' ? true :
    status === 'due' ? (s.status === 'due' || s.status === 'overdue') :
    status === 'new' ? s.status === 'new' :
    (s.status === 'paid' || s.status === 'reviewed');

  // institutions after type/search, with statements filtered by status
  const groups = insts
    .filter(i => (type === 'all' || i.type === type) && i.name.toLowerCase().includes(q.toLowerCase()))
    .map(i => ({ ...i, shown: i.statements.filter(matchStatus) }))
    .filter(i => status === 'all' || i.shown.length > 0);

  const filtering = q || type !== 'all' || status !== 'all';
  const pageCount = Math.ceil(groups.length / PER_PAGE) || 1;
  const pg = Math.min(page, pageCount);
  const visible = groups.slice((pg - 1) * PER_PAGE, pg * PER_PAGE);

  const resetPage = fn => (...a) => { fn(...a); setPage(1); };
  const setStatement = (instId, stmtId, patch) => setInsts(list => list.map(i => i.id !== instId ? i :
    { ...i, statements: i.statements.map(s => s.id === stmtId ? { ...s, ...patch } : s) }));
  const delStatement = (instId, stmtId) => setInsts(list => list.map(i => i.id !== instId ? i :
    { ...i, statements: i.statements.filter(s => s.id !== stmtId) }));

  // Move a statement out of Banking into Receipts or Bills. The converted record
  // is pushed onto the shared store (so the destination screen shows it on its
  // next mount) and the statement is removed from Banking.
  const convertStmt = (instId, stmtId, destKind, amountVal) => {
    const inst = insts.find(i => i.id === instId);
    const stmt0 = inst && inst.statements.find(s => s.id === stmtId);
    if (!inst || !stmt0) return;
    // Statements without a detected figure can't be filed; the drawer collects an
    // amount and passes it here, so the converted record carries a real value.
    const stmt = (amountVal != null)
      ? { ...stmt0, amountVal, amountLabel: stmt0.amountLabel || 'Amount' }
      : stmt0;
    const tm = tmFn(inst.type);
    if (destKind === 'receipt') {
      const rec = statementToReceipt(inst, stmt, tm);
      window.ZD_DATA.receipts = [rec, ...(window.ZD_DATA.receipts || [])];
    } else {
      const bill = statementToBill(inst, stmt, tm);
      window.ZD_DATA.bills = [bill, ...(window.ZD_DATA.bills || [])];
    }
    delStatement(instId, stmtId);
    // Also remove from the shared store so it doesn't reappear when Banking remounts.
    try {
      const gi = window.ZD_DATA.banking.institutions.find(i => i.id === instId);
      if (gi) gi.statements = gi.statements.filter(s => s.id !== stmtId);
    } catch (e) {}
    setSel(null);
    setMoved({ dest: destKind, merchant: inst.name });
  };

  const selInst = sel && insts.find(i => i.id === sel.instId);
  const selStmt = selInst && selInst.statements.find(s => s.id === sel.stmtId);

  const clearFilters = () => { setQ(''); setType('all'); setStatus('all'); setPage(1); };

  const addAccount = form => {
    const id = 'i' + Date.now();
    setInsts(list => [{ id, name: form.name, type: form.type || 'savings', icon: tmFn(form.type).icon,
      account: form.account || 'Account', statements: [] }, ...list]);
    setCreating(false); setPage(1);
  };

  return (
    <div className="screen-inner">
      <div className="statrow">
        <StatCard label="Payments due" value={fmtCcy(toHome(dueTotal, 'USD'), D.fx.home)} sub={`${counts.due} statement${counts.due === 1 ? '' : 's'} to settle`} icon="alert-circle" tint={counts.due ? 'gold' : 'green'} />
        <StatCard label="New this month" value={counts.new} sub="Arrived since May 1" icon="sparkles" tint="blue" />
        <StatCard label="Total statements" value={counts.all} sub={`Across ${insts.length} accounts`} icon="layers" tint="purple" />
      </div>

      <div className="card rise" style={{ overflow:'hidden' }}>
        <div className="card-pad" style={{ paddingBottom:0 }}>
          <div className="section-h">
            <div style={{ display:'flex', alignItems:'center', gap:12 }}>
              <IconChip icon="landmark" tint="gold" size={38} radius={11} />
              <div>
                <div className="t">Statements</div>
                <div className="s">Your bank & credit-card statements, detected from your inbox</div>
              </div>
            </div>
            <Btn variant="primary" icon="plus" kbd="C" title="Connect account — press C" onClick={() => setCreating(true)}>Connect account</Btn>
          </div>

          {/* search */}
          <div className="filterbar">
            <div className="search" style={{ flex:'1 1 220px' }}><Icon name="search" size={17} /><input placeholder="Search institution…" value={q} onChange={resetPage(e => setQ(e.target.value))} />{q && <button className="x-clear" onClick={() => { setQ(''); setPage(1); }}><Icon name="x" size={14} /></button>}</div>
          </div>

          {/* status tabs + account-type pills */}
          <div className="filtbar-2" style={{ borderBottom:'1px solid var(--border)' }}>
            <div className="tabs">
              {[['all','All'],['due','Due'],['new','New'],['filed','Filed']].map(([id,lbl]) => (
                <button key={id} className={status === id ? 'on' : ''} onClick={() => { setStatus(id); setPage(1); }}>{lbl} <span className="tab-n">{counts[id]}</span></button>
              ))}
            </div>
            {filtering && <button className="viewall" onClick={clearFilters}><Icon name="rotate-ccw" size={14} /> Clear filters</button>}
          </div>
          <div className="bank-pills">
            {types.map(t => {
              const n = t.id === 'all' ? insts.length : insts.filter(i => i.type === t.id).length;
              return (
                <button key={t.id} className={`bank-pill ${type === t.id ? 'on' : ''}`} onClick={() => { setType(t.id); setPage(1); }}>
                  {t.icon && <Icon name={t.icon} size={14} />}{t.label}<span className="pc">{n}</span>
                </button>
              );
            })}
          </div>
          <MailboxLegend addrs={insts.map(i => i.mailbox)} />
        </div>

        {/* grouped statements */}
        <div style={{ padding:'4px 18px 4px' }}>
          {visible.map(inst => {
            const tm = tmFn(inst.type);
            const col = collapsed[inst.id];
            const top = inst.shown[0] || inst.statements[0];
            return (
              <div className={`bank-group ${col ? 'col' : ''}`} key={inst.id}>
                <button className="bank-grp-head" onClick={() => setCollapsed(c => ({ ...c, [inst.id]: !c[inst.id] }))}>
                  <IconChip icon={inst.icon} tint={tm.tint} size={38} radius={11} />
                  <div className="bank-grp-meta">
                    <div className="bank-grp-name">{inst.name} <span className={`badge ${ST_META.reviewed.cls}`} style={{ background:tintBg(tm.tint), color:tintFg(tm.tint) }}>{tm.label}</span></div>
                    <div className="bank-grp-sub" style={{ display:'flex', alignItems:'center', gap:8, flexWrap:'wrap' }}><span>{inst.account} · {inst.shown.length} statement{inst.shown.length === 1 ? '' : 's'}</span><MailboxBadge addr={inst.mailbox} variant="mini" /></div>
                  </div>
                  <div className="bank-grp-right">
                    {top && <div className="bank-grp-bal">{top.amountVal != null && top.amountVal !== '' ? <Money amount={top.amountVal} ccy="USD" size={14} /> : <div className="money-home" style={{ fontSize:14, color:'var(--fg-4)' }}>—</div>}<div className="k">{top.amountLabel || 'Amount'}</div></div>}
                    <Icon name="chevron-down" size={18} style={{}} />
                  </div>
                </button>
                <div className="stmt-list">
                  {inst.shown.map(s => {
                    const m = ST_META[s.status];
                    const files = stmtFiles(s);
                    return (
                      <div className="stmt-row" key={s.id} onClick={() => setSel({ instId: inst.id, stmtId: s.id })}>
                        <span className="stmt-ic" style={{ position:'relative' }}><Icon name="file-text" size={17} color="var(--fg-3)" /><span className="stmt-mbx-badge"><MailboxBadge addr={inst.mailbox} variant="dot" /></span></span>
                        <div className="stmt-main">
                          <div className="stmt-period">{s.period}</div>
                          <div className="stmt-sub"><span className={`badge ${m.cls}`}>{m.label}{s.due ? ` · ${s.due}` : ''}</span> {files.length > 1 && <Icon name="paperclip" size={12} style={{ verticalAlign:'-1px', marginRight:1 }} />}{fileSummary(files)}</div>
                        </div>
                        <div className="stmt-amt">{s.amountVal != null && s.amountVal !== '' ? <Money amount={s.amountVal} ccy="USD" size={14} /> : <div className="money-home" style={{ fontSize:14, color:'var(--fg-4)' }}>—</div>}<div className="k">{s.amountLabel || 'Amount'}</div></div>
                        <div className="stmt-acts" onClick={e => e.stopPropagation()}>
                          <StmtAttach files={files} />
                          <button className="iconbtn" title={`View source email · ${inst.sender}`} onClick={() => openSourceEmail(inst, s)}><Icon name="mail" size={16} /></button>
                        </div>
                      </div>
                    );
                  })}
                  {inst.shown.length === 0 && <div className="stmt-row" style={{ cursor:'default', color:'var(--fg-3)', fontSize:13 }}>Connected — your first statement will appear after the next sync.</div>}
                </div>
              </div>
            );
          })}
          {groups.length === 0 && <div className="table-empty" style={{ padding:'48px 0' }}><Icon name="search-x" size={26} color="var(--fg-4)" /><span>No statements match your filters.</span><button className="viewall" onClick={clearFilters}>Clear filters</button></div>}
        </div>

        <Pager page={pg} pageCount={pageCount} total={groups.length} pageSize={PER_PAGE} onPage={setPage} noun="institutions" />
      </div>

      {selStmt && <StatementDrawer inst={selInst} stmt={selStmt} typeMetaFn={tmFn}
        onClose={() => setSel(null)}
        onStatus={st => { setStatement(sel.instId, sel.stmtId, { status: st }); }}
        onConvert={(dest, amountVal) => convertStmt(sel.instId, sel.stmtId, dest, amountVal)}
        onDelete={() => { delStatement(sel.instId, sel.stmtId); setSel(null); }} />}

      {moved && (
        <div className="convert-toast" role="status">
          <span className="ct-ic"><Icon name={moved.dest === 'bill' ? 'dollar-sign' : 'receipt'} size={17} /></span>
          <div className="ct-body">
            <div className="ct-t">{moved.merchant} moved to {moved.dest === 'bill' ? 'Bills' : 'Receipts'}</div>
            <div className="ct-s">Filed as a {moved.dest === 'bill' ? 'payable' : 'receipt'} · removed from Banking</div>
          </div>
          {go && <button className="ct-go" onClick={() => go('bills')}>View<Icon name="arrow-right" size={14} /></button>}
          <button className="ct-x iconbtn" onClick={() => setMoved(null)} title="Dismiss"><Icon name="x" size={15} /></button>
        </div>
      )}

      {creating && <EntityDrawer title="Connect account" sub="Add a bank or card so Zeranda can file its statements"
        icon="landmark" tint="gold" submitLabel="Connect" submitIcon="plus"
        initial={{ name:'', type:'savings', account:'' }}
        fields={[
          { key:'name', label:'Institution', type:'text', icon:'building-2', placeholder:'e.g. Chase', required:true },
          { key:'type', label:'Account type', type:'select', options: types.filter(t => t.id !== 'all').map(t => ({ value:t.id, label:t.label, icon:t.icon, tint:t.tint })) },
          { key:'account', label:'Account reference', type:'text', icon:'hash', placeholder:'e.g. Savings ••4821' },
        ]}
        onClose={() => setCreating(false)} onSubmit={addAccount} />}
    </div>
  );
}
window.Banking = Banking;
