const FR = { wages: 30510 / 36110, employer: 4410 / 36110, vacation: 1190 / 36110, card: 1370 / 12050, comm: 9480 / 12050, promos: 580 / 12050, linen: 620 / 12050, hydro: 2380 / 3240, gas: 860 / 3240 };
const monthsK = () => window.MIZO_FIN.months.map((m) => finK(fsum([m])));
const pyK = () => window.MIZO_FIN.py.map((m) => finK(fsum([m])));

function useFinView() {
  const c = useMizo();
  const P = finPeriod(c.fin.p, c.fin.c, c.L);
  const md = (a, b) => (b ? ((a - b) / Math.abs(b)) * 100 : 0);
  return { ...c, F: window.MIZO_FIN, P, md };
}

// shared drill-downs for headline metrics
function finDrill(key, v) {
  const { L, fmt, P, md, inv } = v; const a = P.cur, b = P.cmp, live = !P.closed;
  const m = fmt.money0, pc = fmt.pct;
  const cmp = (x, y, pct, invert) => ({ lab: P.cmpLab, v: pct ? pc(y) : m(y), delta: pct ? <Pts v={x - y} invert={invert} /> : <Delta v={md(x, y)} invert={invert} /> });
  const daily = P.rows && P.rows.length <= 31 ? { head: [L('Day', 'Jour'), L('Sales', 'Ventes'), L('Tickets', 'Additions')], body: P.rows.map((x) => [fmt.date(x.d, { weekday: 'short', month: 'short', day: 'numeric' }) + (x.partial ? ' *' : ''), fmt.money0(x.rev), fmt.num(Math.round(x.tk))]) } : null;
  const base = { period: P.lab };
  const D = {
    rev: { title: L('Revenue', 'Ventes'), value: m(a.rev), prov: P.partial ? 'e' : 'v', provNote: P.partial ? L('Day not closed yet', 'Journée non fermée') : L('POS daily totals, 26 of 28 days reconciled to the bank', 'Totaux PDV, 26 jours sur 28 rapprochés'), formula: L('Revenue = food sales + beverage sales (before GST/QST, excluding tips)', 'Ventes = aliments + boissons (avant TPS/TVQ, sans pourboires)'),
      inputs: [{ label: L('Food sales', 'Ventes d’aliments'), v: m(a.foodRev), prov: 'v' }, { op: '+', label: L('Beverage sales', 'Ventes de boissons'), v: m(a.bevRev), prov: 'v' }, { tot: true, op: '=', label: L('Revenue', 'Ventes'), v: m(a.rev) }, { label: L('Tickets', 'Additions'), v: fmt.num(Math.round(a.tk)) }, { label: L('Average ticket', 'Addition moyenne'), v: fmt.money(a.avgTk) }],
      cmp: cmp(a.rev, b.rev), rows: daily, notes: [L('Gift-card sales count when redeemed, not when sold.', 'Les cartes-cadeaux comptent à l’utilisation.')], to: ['finance', 'revenue'] },
    gross: { title: L('Gross profit', 'Profit brut'), value: m(a.gross), prov: live ? 'e' : 'v', provNote: L('Cost of goods uses an estimated closing inventory', 'Le coût des marchandises utilise un inventaire de clôture estimé'), formula: L('Gross profit = revenue − cost of goods sold', 'Profit brut = ventes − coût des marchandises vendues'),
      inputs: [{ label: L('Revenue', 'Ventes'), v: m(a.rev), prov: 'v' }, { op: '−', label: L('Food cost of goods', 'Coût des aliments'), v: m(a.foodCogs), prov: 'e' }, { op: '−', label: L('Beverage cost of goods', 'Coût des boissons'), v: m(a.bevCogs), prov: 'e' }, { op: '−', label: L('Packaging', 'Emballages'), v: m(a.pack), prov: 'v' }, { tot: true, op: '=', label: L('Gross profit', 'Profit brut') + ' · ' + pc(a.grossPct), v: m(a.gross) }],
      cmp: cmp(a.gross, b.gross), notes: [L('Gross profit is not net profit — labour, rent and every other expense still come out of it.', 'Le profit brut n’est pas le profit net — main-d’œuvre, loyer et autres dépenses restent à payer.')], to: ['finance', 'costs'] },
    op: { title: L('Operating profit (estimate)', 'Profit d’exploitation (estimation)'), value: m(a.op), prov: 'e', provNote: L('Includes estimated cost of goods, unapproved wages and estimated utilities', 'Inclut coûts estimés, salaires non approuvés et énergie estimée'), formula: L('Operating profit = gross profit − labour − operating expenses', 'Profit d’exploitation = profit brut − main-d’œuvre − frais d’exploitation'),
      inputs: [{ label: L('Gross profit', 'Profit brut'), v: m(a.gross), prov: live ? 'e' : 'v' }, { op: '−', label: L('Labour (wages + employer costs)', 'Main-d’œuvre (salaires + charges)'), v: m(a.lab), prov: live ? 'e' : 'v' }, { op: '−', label: L('Rent', 'Loyer'), v: m(a.rent), prov: 'v' }, { op: '−', label: L('Utilities', 'Énergie'), v: m(a.util), prov: 'e' }, { op: '−', label: L('Card fees, delivery commissions, linen', 'Frais de carte, commissions, lingerie'), v: m(a.other), prov: 'v' }, { tot: true, op: '=', label: L('Operating profit', 'Profit d’exploitation') + ' · ' + pc(a.opPct), v: m(a.op) }],
      cmp: cmp(a.op, b.op), notes: [L('This is before depreciation, loan interest, insurance, owner pay and income tax — so it is not net profit.', 'Avant amortissement, intérêts, assurances, rémunération de la propriétaire et impôts — ce n’est donc pas le profit net.')], to: ['finance', 'pnl'] },
    food: { title: L('Food cost %', '% coût alimentaire'), value: pc(a.foodPct), prov: live ? 'e' : 'v', formula: L('Food cost % = food cost of goods ÷ food sales', '% coût alimentaire = coût des aliments ÷ ventes d’aliments'),
      inputs: [{ label: L('Food cost of goods', 'Coût des aliments'), v: m(a.foodCogs), prov: 'e', note: L('Opening inventory + food purchases − closing inventory', 'Inventaire d’ouverture + achats − inventaire de clôture') }, { op: '÷', label: L('Food sales', 'Ventes d’aliments'), v: m(a.foodRev), prov: 'v' }, { tot: true, op: '=', label: L('Food cost %', '% coût alimentaire'), v: pc(a.foodPct) }],
      cmp: cmp(a.foodPct, b.foodPct, true, true), notes: [L('Beverages and packaging are tracked separately so they don’t hide food problems.', 'Boissons et emballages sont suivis à part pour ne pas cacher les problèmes de nourriture.')], to: ['finance', 'foodbev'] },
    lab: { title: L('Labour %', '% main-d’œuvre'), value: pc(a.labPct), prov: live ? 'e' : 'v', provNote: L('Current pay period not yet approved', 'Période de paie non approuvée'), formula: L('Labour % = (wages + employer contributions + vacation pay) ÷ revenue', '% main-d’œuvre = (salaires + charges + vacances) ÷ ventes'),
      inputs: [{ label: L('Wages', 'Salaires'), v: m(a.lab * FR.wages), prov: live ? 'e' : 'v' }, { op: '+', label: L('Employer contributions (QPP, EI, QPIP, FSS, CNESST)', 'Cotisations (RRQ, AE, RQAP, FSS, CNESST)'), v: m(a.lab * FR.employer), prov: 'e' }, { op: '+', label: L('Vacation pay (4%)', 'Vacances (4 %)'), v: m(a.lab * FR.vacation), prov: 'e' }, { tot: true, op: '=', label: L('Labour', 'Main-d’œuvre'), v: m(a.lab) }, { op: '÷', label: L('Revenue', 'Ventes'), v: m(a.rev), prov: 'v' }],
      cmp: cmp(a.labPct, b.labPct, true, true), notes: [L('Tips are paid through payroll but are not a labour cost.', 'Les pourboires passent par la paie mais ne sont pas un coût.')], to: ['finance', 'labour'] },
    prime: { title: L('Prime cost %', '% coût principal'), value: pc(a.primePct), prov: 'e', formula: L('Prime cost % = (cost of goods sold + labour) ÷ revenue', '% coût principal = (coût des marchandises + main-d’œuvre) ÷ ventes'),
      inputs: [{ label: L('Cost of goods sold', 'Coût des marchandises'), v: m(a.cogs), prov: 'e' }, { op: '+', label: L('Labour', 'Main-d’œuvre'), v: m(a.lab), prov: live ? 'e' : 'v' }, { tot: true, op: '=', label: L('Prime cost', 'Coût principal'), v: m(a.prime) }, { op: '÷', label: L('Revenue', 'Ventes'), v: m(a.rev), prov: 'v' }],
      cmp: cmp(a.primePct, b.primePct, true, true), notes: [L('Prime cost is the part of spending you can change week to week. Under 63% is the target set in Budget.', 'Le coût principal est la part des dépenses que vous pouvez changer chaque semaine. Cible : moins de 63 %.')], to: ['finance', 'prime'] },
  };
  if (key === 'inv') { const rows = inv.map((i) => ({ i, v: i.onHand * i.cost })).sort((x, y) => y.v - x.v); const tot = rows.reduce((s, x) => s + x.v, 0); return { ...base, period: L('Right now', 'En ce moment'), title: L('Inventory value', 'Valeur de l’inventaire'), value: m(tot), prov: 'e', provNote: L('Last count + deliveries − theoretical usage', 'Dernier compte + livraisons − usage théorique'), formula: L('Inventory value = Σ (quantity on hand × latest unit cost)', 'Valeur = Σ (quantité en stock × dernier coût unitaire)'), inputs: [{ label: L('Items tracked', 'Articles suivis'), v: inv.length }, { label: L('Last full count', 'Dernier inventaire complet'), v: L('Sun, Oct 25', 'dim. 25 oct.'), prov: 'v' }, { tot: true, op: '=', label: L('Value on hand', 'Valeur en stock'), v: m(tot) }], rows: { head: [L('Item', 'Article'), L('On hand', 'En stock'), L('Value', 'Valeur')], body: rows.slice(0, 8).map((x) => [x.i.name[v.lang], fmt.num(x.i.onHand) + ' ' + x.i.unit, fmt.money0(x.v)]) }, rowsTitle: L('Largest items', 'Articles les plus importants'), to: ['inventory', 'stock'], toLabel: L('Open stock levels', 'Voir les niveaux de stock') }; }
  return { ...base, ...D[key] };
}

function FinHead({ sub, report }) { const { L, openExport } = useMizo(); return <><PageHead sub={sub}><FinPicker /><button className="btn btn-secondary" onClick={() => openExport({ kind: report || 'summary' })}><Icon n="printer" />{L('Print / PDF', 'Imprimer / PDF')}</button></PageHead><ProvLegend /></>; }

function FinSummary() {
  const v = useFinView(); const { L, lang, fmt, P, md, calc, go, F } = v; const a = P.cur, b = P.cmp;
  const dayN = P.rows ? P.rows.length : 363;
  const below = { dep: (1850 * dayN) / 30.4, int: (310 * dayN) / 30.4, ins: (640 * dayN) / 30.4 };
  const pbt = a.op - below.dep - below.int - below.ins;
  const mk = monthsK();
  const steps = [
    { label: L('Revenue', 'Ventes'), total: true, v: a.rev, onClick: () => calc(finDrill('rev', v)) },
    { label: L('Cost of goods', 'Marchandises'), from: a.rev, to: a.gross, onClick: () => calc(finDrill('gross', v)) },
    { label: L('Gross profit', 'Profit brut'), total: true, v: a.gross, onClick: () => calc(finDrill('gross', v)) },
    { label: L('Labour', 'Main-d’œuvre'), from: a.gross, to: a.gross - a.lab, onClick: () => calc(finDrill('lab', v)) },
    { label: L('Operating costs', 'Frais d’exploitation'), from: a.gross - a.lab, to: a.op, onClick: () => calc(finDrill('op', v)) },
    { label: L('Operating profit', 'Profit d’exploitation'), total: true, v: a.op, hl: true, onClick: () => calc(finDrill('op', v)) },
    { label: L('Below the line', 'Hors exploitation'), from: a.op, to: pbt },
    { label: L('Before tax (est.)', 'Avant impôt (est.)'), total: true, v: pbt },
  ];
  const pbtD = { period: P.lab, title: L('Profit before tax (estimate)', 'Profit avant impôt (estimation)'), value: fmt.money0(pbt), prov: 'e', formula: L('Operating profit − depreciation − loan interest − insurance', 'Profit d’exploitation − amortissement − intérêts − assurances'), inputs: [{ label: L('Operating profit', 'Profit d’exploitation'), v: fmt.money0(a.op), prov: 'e' }, { op: '−', label: L('Depreciation', 'Amortissement'), v: fmt.money0(below.dep), prov: 'e', note: L('No asset register — estimated', 'Aucun registre — estimé') }, { op: '−', label: L('Loan interest', 'Intérêts'), v: fmt.money0(below.int), prov: 'v' }, { op: '−', label: L('Insurance', 'Assurances'), v: fmt.money0(below.ins), prov: 'm', note: L('Not entered — estimated from cash flow schedule', 'Non saisi — estimé selon la trésorerie') }, { tot: true, op: '=', label: L('Profit before tax', 'Profit avant impôt'), v: fmt.money0(pbt) }], notes: [L('Still before paying the owner and before income tax. This is the closest MIZO can get to net profit until those are entered.', 'Toujours avant la rémunération de la propriétaire et l’impôt. C’est le plus proche du profit net possible pour l’instant.')], to: ['finance', 'pnl'] };
  return (
    <div className="page">
      <FinHead sub={L('Every number here opens up to show how it was calculated and where the data came from.', 'Chaque chiffre s’ouvre pour montrer son calcul et la source des données.')} />
      <section className="kpis">
        <Metric hero ic="cash-register" label={L('Revenue', 'Ventes')} value={fmt.money0(a.rev)} delta={<Delta v={md(a.rev, b.rev)} />} cmpLab={P.cmpLab} prov={P.partial ? 'e' : 'v'} onClick={() => calc(finDrill('rev', v))} />
        <Metric ic="chart-pie-slice" label={L('Gross profit', 'Profit brut')} value={fmt.money0(a.gross)} delta={<Delta v={md(a.gross, b.gross)} />} sub={fmt.pct(a.grossPct) + ' ' + L('margin', 'de marge')} prov={P.closed ? 'v' : 'e'} onClick={() => calc(finDrill('gross', v))} />
        <Metric ic="coins" label={L('Operating profit', 'Profit d’exploitation')} value={fmt.money0(a.op)} delta={<Delta v={md(a.op, b.op)} />} sub={fmt.pct(a.opPct) + ' ' + L('margin', 'de marge')} prov="e" onClick={() => calc(finDrill('op', v))} />
        <Metric ic="receipt" label={L('Profit before tax', 'Profit avant impôt')} value={fmt.money0(pbt)} sub={L('before owner pay', 'avant rémunération')} prov="e" onClick={() => calc(pbtD)} />
      </section>
      <section className="kpis">
        <Metric ic="bowl-food" label={L('Food cost', 'Coût alimentaire')} value={fmt.pct(a.foodPct)} delta={<Pts v={a.foodPct - b.foodPct} invert />} cmpLab={P.cmpLab} prov={P.closed ? 'v' : 'e'} onClick={() => calc(finDrill('food', v))} />
        <Metric ic="wine" label={L('Beverage cost', 'Coût des boissons')} value={fmt.pct(a.bevPct)} sub={L('of beverage sales', 'des ventes de boissons')} prov="e" onClick={() => go('finance', { tab: 'foodbev' })} />
        <Metric ic="users-three" label={L('Labour', 'Main-d’œuvre')} value={fmt.pct(a.labPct)} delta={<Pts v={a.labPct - b.labPct} invert />} cmpLab={P.cmpLab} prov={P.closed ? 'v' : 'e'} onClick={() => calc(finDrill('lab', v))} />
        <Metric ic="scales" label={L('Prime cost', 'Coût principal')} value={fmt.pct(a.primePct)} delta={<Pts v={a.primePct - b.primePct} invert />} cmpLab={P.cmpLab} prov="e" onClick={() => calc(finDrill('prime', v))} />
      </section>
      <section className="grid-2-1">
        <div className="panel">
          <div className="panel-head"><div><h3>{L('From sales to profit', 'Des ventes au profit')}</h3><p className="muted">{P.lab} · {L('tap any bar for the detail', 'touchez une barre pour le détail')}</p></div></div>
          <Waterfall steps={steps} fmtv={fmt.kmoney} />
        </div>
        <div className="panel">
          <div className="panel-head"><div><h3>{L('What MIZO doesn’t know yet', 'Ce que MIZO ne sait pas encore')}</h3><p className="muted">{F.gaps.length} {L('gaps that affect these numbers', 'lacunes qui touchent ces chiffres')}</p></div></div>
          <ul className="alerts">{F.gaps.slice(0, 6).map((g) => <li key={g.k} className="alert"><span className="alert-ic warn"><Icon n={g.ic} /></span><div className="alert-text"><div>{g.t[lang]}</div><div className="muted sm">{g.d[lang]}</div></div>{g.to ? <button className="btn btn-ghost" onClick={() => go(g.to[0], { tab: g.to[1] })}><Icon n="arrow-right" /></button> : null}</li>)}</ul>
        </div>
      </section>
      <div className="panel">
        <div className="panel-head"><div><h3>{L('Margins, last 12 months', 'Marges, 12 derniers mois')}</h3><p className="muted">{L('October is month-to-date', 'Octobre : à ce jour')}</p></div><div className="legend"><span><i className="dot lc-sw lc-a"></i>{L('Gross', 'Brute')}</span><span><i className="dot lc-sw lc-warn"></i>{L('Prime cost', 'Coût principal')}</span><span><i className="dot lc-sw lc-pos"></i>{L('Operating', 'Exploitation')}</span></div></div>
        <LineChart labels={F.months.map((x) => x.label[lang])} series={[{ name: L('Gross margin', 'Marge brute'), values: mk.map((x) => x.grossPct), tone: 'a' }, { name: L('Prime cost', 'Coût principal'), values: mk.map((x) => x.primePct), tone: 'warn' }, { name: L('Operating margin', 'Marge d’exploitation'), values: mk.map((x) => x.opPct), tone: 'pos' }]} fmtv={(x) => fmt.pct(x)} height={220} />
      </div>
    </div>
  );
}

function FinPnL() {
  const v = useFinView(); const { L, fmt, P, md, calc, toast } = v; const a = P.cur, b = P.cmp, live = !P.closed;
  const dayN = P.rows ? P.rows.length : 363, bl = (x) => (x * dayN) / 30.4;
  const row = (label, x, y, prov, opt = {}) => ({ label, x, y, prov, ...opt });
  const S = [
    [L('Revenue', 'Revenus'), [row(L('Food sales', 'Ventes d’aliments'), a.foodRev, b.foodRev, 'v'), row(L('Beverage sales', 'Ventes de boissons'), a.bevRev, b.bevRev, 'v')], row(L('Total revenue', 'Total des revenus'), a.rev, b.rev, 'v', { k: 'rev' })],
    [L('Cost of goods sold', 'Coût des marchandises vendues'), [row(L('Food', 'Aliments'), a.foodCogs, b.foodCogs, 'e', { cost: 1 }), row(L('Beverages', 'Boissons'), a.bevCogs, b.bevCogs, 'e', { cost: 1 }), row(L('Packaging', 'Emballages'), a.pack, b.pack, 'v', { cost: 1 })], row(L('Gross profit', 'Profit brut'), a.gross, b.gross, live ? 'e' : 'v', { k: 'gross', m: a.grossPct })],
    [L('Labour', 'Main-d’œuvre'), [row(L('Wages', 'Salaires'), a.lab * FR.wages, b.lab * FR.wages, live ? 'e' : 'v', { cost: 1 }), row(L('Employer contributions', 'Charges sociales'), a.lab * FR.employer, b.lab * FR.employer, 'e', { cost: 1 }), row(L('Vacation pay', 'Indemnités de vacances'), a.lab * FR.vacation, b.lab * FR.vacation, 'e', { cost: 1 })], row(L('Prime cost (goods + labour)', 'Coût principal (marchandises + main-d’œuvre)'), a.prime, b.prime, 'e', { k: 'prime', cost: 1, m: a.primePct })],
    [L('Operating expenses', 'Frais d’exploitation'), [row(L('Rent', 'Loyer'), a.rent, b.rent, 'v', { cost: 1 }), row(L('Electricity (Hydro-Québec)', 'Électricité (Hydro-Québec)'), a.util * FR.hydro, b.util * FR.hydro, 'e', { cost: 1 }), row(L('Natural gas (Énergir)', 'Gaz naturel (Énergir)'), a.util * FR.gas, b.util * FR.gas, 'e', { cost: 1 }), row(L('Card processing fees', 'Frais de traitement des cartes'), a.other * FR.card, b.other * FR.card, 'e', { cost: 1 }), row(L('Delivery app commissions', 'Commissions de livraison'), a.other * FR.comm, b.other * FR.comm, 'v', { cost: 1 }), row(L('Delivery app promotions', 'Promotions des applis'), a.other * FR.promos, b.other * FR.promos, 'v', { cost: 1 }), row(L('Linen service', 'Lingerie'), a.other * FR.linen, b.other * FR.linen, 'v', { cost: 1 })], row(L('Operating profit', 'Profit d’exploitation'), a.op, b.op, 'e', { k: 'op', m: a.opPct, hl: 1 })],
    [L('Below operating profit', 'Sous le profit d’exploitation'), [row(L('Depreciation', 'Amortissement'), bl(1850), bl(1850), 'e', { cost: 1 }), row(L('Loan interest', 'Intérêts sur prêt'), bl(310), bl(310), 'v', { cost: 1 }), row(L('Insurance', 'Assurances'), bl(640), bl(640), 'm', { cost: 1 }), row(L('Owner pay', 'Rémunération de la propriétaire'), null, null, 'm')], row(L('Profit before tax (estimate)', 'Profit avant impôt (estimation)'), a.op - bl(2800), b.op - bl(2800), 'e', { m: ((a.op - bl(2800)) / a.rev) * 100 })],
  ];
  const open = (r) => (r.k ? calc(finDrill(r.k, v)) : calc({ period: P.lab, title: r.label, value: r.x == null ? '—' : fmt.money0(r.x), prov: r.prov, inputs: [{ label: L('This period', 'Cette période'), v: r.x == null ? L('Not recorded', 'Non saisi') : fmt.money(r.x), prov: r.prov }, { label: L('Share of revenue', 'Part des ventes'), v: r.x == null ? '—' : fmt.pct((r.x / a.rev) * 100) }, { label: P.cmpLab, v: r.y == null ? '—' : fmt.money(r.y) }], notes: [r.prov === 'v' ? L('Matched to supplier invoices, statements or the lease.', 'Concorde avec factures, relevés ou bail.') : r.prov === 'm' ? L('Not entered in MIZO. Add it so profit is complete.', 'Non saisi dans MIZO. Ajoutez-le pour un profit complet.') : L('Modelled from October’s split of this cost — the bill or statement isn’t in MIZO yet.', 'Modélisé selon la répartition d’octobre — la facture n’est pas encore dans MIZO.')] }));
  const line = (r, cls) => { const d = r.x != null && r.y ? md(r.x, r.y) : 0; return (
    <tr key={r.label} className={'clickable ' + cls} onClick={() => open(r)}>
      <td>{r.label} <Prov k={r.prov} short /></td><td className="num tnum">{r.x == null ? <span className="muted">—</span> : fmt.money0(r.x)}</td><td className="num tnum muted hide-sm">{r.m != null ? fmt.pct(r.m) : r.x != null ? fmt.pct((r.x / a.rev) * 100) : ''}</td><td className="num tnum hide-sm">{r.y == null ? '—' : fmt.money0(r.y)}</td>
      <td className="num">{r.x == null || Math.abs(d) < 0.05 ? <span className="muted">—</span> : <span className={'tnum ' + ((r.cost ? d < 0 : d > 0) ? 'txt-pos' : 'txt-neg')}>{d > 0 ? '+' : '−'}{fmt.pct(Math.abs(d))}</span>}</td>
    </tr>
  ); };
  const exportCsv = () => { const rows = [['Line', P.lab, P.cmpLab, 'Status'], ...S.flatMap(([g, rs, t]) => [...rs, t].map((r) => [r.label, r.x == null ? '' : r.x.toFixed(2), r.y == null ? '' : r.y.toFixed(2), { v: 'verified', e: 'estimated', m: 'missing' }[r.prov]]))]; const el = document.createElement('a'); el.href = URL.createObjectURL(new Blob([rows.map((r) => r.map((c) => '"' + c + '"').join(',')).join('\n')], { type: 'text/csv' })); el.download = 'souvlaki-village-profit-and-loss.csv'; el.click(); toast(L('Profit & loss exported', 'État des résultats exporté')); };
  return (
    <div className="page">
      <PageHead sub={L('The full statement, line by line. Click any line to see its source.', 'L’état complet, ligne par ligne. Cliquez sur une ligne pour voir sa source.')}><FinPicker /><button className="btn btn-secondary" onClick={exportCsv}><Icon n="download-simple" />{L('CSV for accountant', 'CSV pour le comptable')}</button><button className="btn btn-secondary" onClick={() => v.openExport({ kind: 'pnl' })}><Icon n="printer" />{L('Print / PDF', 'Imprimer / PDF')}</button></PageHead>
      <ProvLegend />
      <div className="panel panel-flush">
        <div className="table-scroll">
          <table className="table mtable pl">
            <thead><tr><th>{P.lab}</th><th className="num">{L('Amount', 'Montant')}</th><th className="num hide-sm">{L('% of sales', '% des ventes')}</th><th className="num hide-sm">{P.cmpLab}</th><th className="num">{L('Change', 'Écart')}</th></tr></thead>
            <tbody>{S.map(([g, rs, t]) => <React.Fragment key={g}><tr className="pl-grp"><td colSpan="5">{g}</td></tr>{rs.map((r) => line(r, 'pl-sub'))}{line(t, 'pl-tot' + (t.hl ? ' pl-net' : ''))}</React.Fragment>)}</tbody>
          </table>
        </div>
      </div>
      <div className="suggest"><Icon n="info" /><div>{L('Operating profit is what the restaurant earns from running day to day. Net profit would also subtract depreciation, interest, insurance, owner pay and income tax — some of which aren’t in MIZO yet.', 'Le profit d’exploitation est ce que le restaurant gagne au quotidien. Le profit net soustrairait aussi amortissement, intérêts, assurances, rémunération et impôt — certains ne sont pas encore dans MIZO.')}</div></div>
    </div>
  );
}

function FinRevenue() {
  const v = useFinView(); const { L, lang, fmt, F, O, P, md, calc, recipes, D } = v; const a = P.cur, b = P.cmp;
  const mk = monthsK(), pk = pyK();
  const oct = F.days.filter((x) => x.d >= '2026-10-01');
  const back7 = (d) => { const t = new Date(d + 'T12:00'); t.setDate(t.getDate() - 7); return t.toISOString().slice(0, 10); };
  const byD = Object.fromEntries(F.days.map((x) => [x.d, x]));
  const cat = Object.keys(D.recipeCats).map((k) => ({ k, v: recipes.filter((r) => r.cat === k).reduce((s, r) => s + r.price * r.sold, 0) }));
  const catT = cat.reduce((s, x) => s + x.v, 0);
  const yoy = md(mk[11].rev, pk[11].rev);
  return (
    <div className="page">
      <FinHead sub={L('Where sales come from — by month, day, channel, category and time of day.', 'D’où viennent les ventes — par mois, jour, canal, catégorie et moment de la journée.')} />
      <section className="kpis">
        <Metric hero ic="cash-register" label={L('Revenue', 'Ventes')} value={fmt.money0(a.rev)} delta={<Delta v={md(a.rev, b.rev)} />} cmpLab={P.cmpLab} prov={P.partial ? 'e' : 'v'} onClick={() => calc(finDrill('rev', v))} />
        <Metric ic="receipt" label={L('Tickets', 'Additions')} value={fmt.num(Math.round(a.tk))} delta={<Delta v={md(a.tk, b.tk)} />} prov="v" onClick={() => calc(finDrill('rev', v))} />
        <Metric ic="tag" label={L('Average ticket', 'Addition moyenne')} value={fmt.money(a.avgTk)} delta={<Delta v={md(a.avgTk, b.avgTk)} />} prov="v" onClick={() => calc({ period: P.lab, title: L('Average ticket', 'Addition moyenne'), value: fmt.money(a.avgTk), prov: 'v', formula: L('Average ticket = revenue ÷ tickets', 'Addition moyenne = ventes ÷ additions'), inputs: [{ label: L('Revenue', 'Ventes'), v: fmt.money0(a.rev), prov: 'v' }, { op: '÷', label: L('Tickets', 'Additions'), v: fmt.num(Math.round(a.tk)), prov: 'v' }, { tot: true, op: '=', label: L('Average ticket', 'Addition moyenne'), v: fmt.money(a.avgTk) }] })} />
        <Metric ic="trend-up" label={L('Growth vs last year', 'Croissance vs l’an dernier')} value={(yoy > 0 ? '+' : '') + fmt.pct(yoy)} sub={L('October to date', 'Octobre à ce jour')} prov="v" onClick={() => calc({ title: L('Growth vs last year', 'Croissance annuelle'), value: fmt.pct(yoy), prov: 'v', formula: L('(Oct 1–28, 2026 − Oct 1–28, 2025) ÷ Oct 1–28, 2025', '(1–28 oct. 2026 − 1–28 oct. 2025) ÷ 1–28 oct. 2025'), inputs: [{ label: '2026', v: fmt.money0(mk[11].rev), prov: 'v' }, { op: '−', label: '2025', v: fmt.money0(pk[11].rev), prov: 'v' }, { tot: true, op: '=', label: L('Growth', 'Croissance'), v: fmt.pct(yoy) }], rows: { head: [L('Month', 'Mois'), '2026', '2025', '%'], body: F.months.map((m, i) => [m.label[lang], fmt.money0(mk[i].rev), fmt.money0(pk[i].rev), fmt.pct(md(mk[i].rev, pk[i].rev))]) } })} />
      </section>
      <section className="grid-2-1">
        <div className="panel">
          <div className="panel-head"><div><h3>{L('Monthly revenue', 'Ventes mensuelles')}</h3><p className="muted">{L('This year vs. last year · October to date', 'Cette année vs l’an dernier · octobre à ce jour')}</p></div><div className="legend"><span><i className="dot dot-a"></i>{L('This year', 'Cette année')}</span><span><i className="dot dot-b"></i>{L('Last year', 'L’an dernier')}</span></div></div>
          <BarChart data={F.months.map((m, i) => ({ label: m.label[lang], a: mk[i].rev, b: pk[i].rev }))} la={L('This year', 'Cette année')} lb={L('Last year', 'L’an dernier')} fmtv={(x, full) => (full ? fmt.money0(x) : fmt.kmoney(x))} height={220} highlightLast />
        </div>
        <div className="panel"><div className="panel-head"><div><h3>{L('By channel', 'Par canal')}</h3><p className="muted">{L('October to date', 'Octobre à ce jour')}</p></div></div><HBars items={O.channels.map((c) => ({ label: c.name[lang], v: c.v, sub: fmt.pct((c.v / 112860) * 100) }))} fmtv={fmt.money0} /></div>
      </section>
      <div className="panel">
        <div className="panel-head"><div><h3>{L('Daily revenue, October', 'Ventes quotidiennes, octobre')}</h3><p className="muted">{L('Dashed line is the same weekday one week earlier · today is partial', 'Pointillé : même jour la semaine précédente · aujourd’hui partiel')}</p></div></div>
        <LineChart labels={oct.map((x) => fmt.date(x.d, { day: 'numeric', month: 'short' }))} series={[{ name: L('This day', 'Ce jour'), values: oct.map((x) => x.rev), tone: 'a' }, { name: L('Week before', 'Semaine précédente'), values: oct.map((x) => (byD[back7(x.d)] || {}).rev), tone: 'b', dash: 1 }]} fmtv={(x, full) => (full ? fmt.money0(x) : fmt.kmoney(x))} height={200} every={4} />
      </div>
      <section className="grid-1-1">
        <div className="panel"><div className="panel-head"><div><h3>{L('Food vs. beverages', 'Aliments vs boissons')}</h3><p className="muted">{P.lab}</p></div></div><HBars items={[{ label: L('Food', 'Aliments'), v: a.foodRev }, { label: L('Beverages', 'Boissons'), v: a.bevRev }]} fmtv={fmt.money0} /><div className="dr-label" style={{ marginTop: '.4rem' }}>{L('Food sales by menu category (mix)', 'Ventes d’aliments par catégorie')}</div><HBars items={cat.sort((x, y) => y.v - x.v).map((x) => ({ label: D.recipeCats[x.k][lang], v: (x.v / catT) * a.foodRev }))} fmtv={fmt.money0} /></div>
        <div className="panel"><div className="panel-head"><div><h3>{L('By time of day', 'Par moment de la journée')}</h3><p className="muted">{L('October to date', 'Octobre à ce jour')}</p></div></div><HBars items={O.dayparts.map((d) => ({ label: d.name[lang], v: d.v }))} fmtv={fmt.money0} /></div>
      </section>
    </div>
  );
}

Object.assign(window, { FR, monthsK, pyK, useFinView, finDrill, FinHead, FinSummary, FinPnL, FinRevenue });
