const TODAY = '2026-10-28';
const daysTo = (d) => Math.round((new Date(d + 'T12:00') - new Date(TODAY + 'T12:00')) / 86400000);
const locName = (O, id, lang) => { const l = O.locations.find((x) => x.id === id); return l ? l.name[lang] : id; };
// qty per location: primary location holds whatever isn't recorded elsewhere
const locQty = (i, ops) => { const m = ops.meta[i.id] || []; const other = ops.locq[i.id] || {}; const out = { ...other }; out[m[0] || 'dry'] = Math.max(0, i.onHand - Object.values(other).reduce((s, v) => s + v, 0)); return out; };

function AllergenTags({ list, lang }) {
  const { O } = useMizo();
  if (!list || !list.length) return <span className="muted">—</span>;
  return <span className="tagrow">{list.map((a) => <span key={a} className="tag tag-outline">{(O.allergens.find((x) => x[0] === a) || [a, { en: a, fr: a }])[1][lang]}</span>)}</span>;
}

function Ingredients() {
  const { L, lang, fmt, D, O, inv, setInv, ops, upd, toast } = useMizo();
  const [q, setQ] = React.useState('');
  const [cat, setCat] = React.useState('all');
  const [loc, setLoc] = React.useState('all');
  const [sel, setSel] = React.useState(null);
  const rows = inv.filter((i) => (cat === 'all' || i.cat === cat) && (loc === 'all' || (ops.meta[i.id] || [])[0] === loc) && (i.name[lang] + (ops.meta[i.id] || [])[1]).toLowerCase().includes(q.toLowerCase()));
  const sup = (id) => (D.suppliers.find((s) => s.id === id) || {}).name;
  return (
    <div className="page">
      <PageHead sub={L('Every ingredient you buy: supplier, pack size, storage, shelf life, allergens and barcode.', 'Chaque ingrédient acheté : fournisseur, format, entreposage, durée de vie, allergènes et code-barres.')}>
        <button className="btn btn-primary" onClick={() => setSel('new')}><Icon n="plus" />{L('Add ingredient', 'Ajouter un ingrédient')}</button>
      </PageHead>
      <div className="panel panel-flush">
        <div className="toolbar">
          <label className="search"><Icon n="magnifying-glass" /><input className="input" placeholder={L('Name or barcode', 'Nom ou code-barres')} value={q} onChange={(e) => setQ(e.target.value)} /></label>
          <Seg size="sm" value={cat} onChange={setCat} options={[['all', L('All', 'Tout')], ...Object.entries(D.cats).map(([k, v]) => [k, v[lang]])]} />
          <select className="input" style={{ maxWidth: 220 }} value={loc} onChange={(e) => setLoc(e.target.value)}><option value="all">{L('All locations', 'Tous les lieux')}</option>{O.locations.map((l) => <option key={l.id} value={l.id}>{l.name[lang]}</option>)}</select>
        </div>
        <div className="table-scroll">
          <table className="table mtable">
            <thead><tr><th>{L('Ingredient', 'Ingrédient')}</th><th className="hide-sm">{L('Supplier', 'Fournisseur')}</th><th className="hide-md">{L('Pack', 'Format')}</th><th className="num">{L('Cost', 'Coût')}</th><th className="hide-sm">{L('Stored in', 'Entreposé')}</th><th className="num hide-md">{L('Shelf life', 'Durée')}</th><th className="hide-sm">{L('Allergens', 'Allergènes')}</th></tr></thead>
            <tbody>{rows.map((i) => { const m = ops.meta[i.id] || []; return (
              <tr key={i.id} className="clickable" onClick={() => setSel(i.id)}>
                <td><div className="cell-main">{i.name[lang]}</div><div className="cell-sub tnum"><Icon n="barcode" /> {m[1] || '—'}</div></td>
                <td className="hide-sm">{sup(i.sup)}</td><td className="hide-md">{m[2] ? m[2][lang] : '—'}</td>
                <td className="num tnum">{fmt.money(i.cost)}<div className="cell-sub">/ {i.unit}</div></td>
                <td className="hide-sm">{locName(O, m[0], lang)}</td><td className="num tnum hide-md">{m[3] ? m[3] + ' ' + L('days', 'j') : '—'}</td><td className="hide-sm"><AllergenTags list={m[4]} lang={lang} /></td>
              </tr>
            ); })}</tbody>
          </table>
          {!rows.length ? <div className="empty">{L('No ingredients match.', 'Aucun ingrédient.')}</div> : null}
        </div>
      </div>
      <Drawer open={!!sel} onClose={() => setSel(null)}>{sel ? <IngredientForm id={sel} onClose={() => setSel(null)} /> : null}</Drawer>
    </div>
  );
}

function IngredientForm({ id, onClose }) {
  const { L, lang, fmt, D, O, inv, setInv, ops, upd, toast } = useMizo();
  const cur = inv.find((i) => i.id === id);
  const m = ops.meta[id] || ['dry', '', { en: '', fr: '' }, 7, [], 100, 0];
  const [f, setF] = React.useState(cur ? { name: cur.name[lang], cat: cur.cat, unit: cur.unit, par: cur.par, cost: cur.cost, sup: cur.sup, loc: m[0], code: m[1], pack: m[2][lang], shelf: m[3], al: m[4] } : { name: '', cat: 'pantry', unit: 'kg', par: 5, cost: '', sup: 's5', loc: 'dry', code: '', pack: '', shelf: 30, al: [] });
  const save = () => {
    if (!f.name.trim()) return;
    const nid = cur ? id : f.name.toLowerCase().replace(/[^a-z0-9]+/g, '').slice(0, 12) + Date.now() % 1000;
    const nm = cur ? { ...cur.name, [lang]: f.name } : { en: f.name, fr: f.name };
    if (cur) setInv(inv.map((i) => (i.id === id ? { ...i, name: nm, cat: f.cat, unit: f.unit, par: Number(f.par), sup: f.sup } : i)));
    else setInv([...inv, { id: nid, name: nm, cat: f.cat, unit: f.unit, onHand: 0, par: Number(f.par), cost: Number(f.cost) || 0, sup: f.sup, trend: 0, hist: Array(6).fill(Number(f.cost) || 0) }]);
    upd('meta', (mm) => ({ ...mm, [nid]: [f.loc, f.code, { ...m[2], [lang]: f.pack }, Number(f.shelf), f.al, m[5], m[6]] }));
    toast(cur ? L('Ingredient updated', 'Ingrédient mis à jour') : L('Ingredient added', 'Ingrédient ajouté')); onClose();
  };
  const fl = (k) => (e) => setF({ ...f, [k]: e.target.value });
  return (
    <div className="dr">
      <div className="dr-head"><div><div className="card-kicker">{cur ? L('Ingredient', 'Ingrédient') : L('New ingredient', 'Nouvel ingrédient')}</div><h2>{f.name || '—'}</h2></div><button className="btn btn-icon btn-secondary" onClick={onClose} aria-label="Close"><Icon n="x" /></button></div>
      <div className="dr-sec">
        <div className="form-grid">
          <div className="field span-2"><label>{L('Name', 'Nom')}</label><input className="input" value={f.name} onChange={fl('name')} /></div>
          <div className="field"><label>{L('Category', 'Catégorie')}</label><select className="input" value={f.cat} onChange={fl('cat')}>{Object.entries(D.cats).map(([k, v]) => <option key={k} value={k}>{v[lang]}</option>)}</select></div>
          <div className="field"><label>{L('Counting unit', 'Unité')}</label><select className="input" value={f.unit} onChange={fl('unit')}>{['kg', 'L', 'ea'].map((u) => <option key={u}>{u}</option>)}</select></div>
          <div className="field"><label>{L('Supplier', 'Fournisseur')}</label><select className="input" value={f.sup} onChange={fl('sup')}>{D.suppliers.map((s) => <option key={s.id} value={s.id}>{s.name}</option>)}</select></div>
          <div className="field"><label>{L('Pack size', 'Format')}</label><input className="input" value={f.pack} onChange={fl('pack')} placeholder={L('e.g. 10 kg case', 'ex. caisse 10 kg')} /></div>
          <div className="field"><label>{L('Par level', 'Niveau cible')} ({f.unit})</label><input className="input" type="number" value={f.par} onChange={fl('par')} /></div>
          <div className="field"><label>{L('Unit cost (CAD)', 'Coût unitaire (CAD)')}</label>{cur ? <div className="input" style={{ display: 'flex', alignItems: 'center' }}>{fmt.money(cur.cost)} <span className="muted sm" style={{ marginLeft: '.5rem' }}>{L('from last invoice', 'dernière facture')}</span></div> : <input className="input" type="number" step="0.01" value={f.cost} onChange={fl('cost')} />}</div>
          <div className="field"><label>{L('Stored in', 'Entreposé')}</label><select className="input" value={f.loc} onChange={fl('loc')}>{O.locations.map((l) => <option key={l.id} value={l.id}>{l.name[lang]}</option>)}</select></div>
          <div className="field"><label>{L('Shelf life (days)', 'Durée de vie (jours)')}</label><input className="input" type="number" value={f.shelf} onChange={fl('shelf')} /></div>
          <div className="field span-2"><label>{L('Barcode', 'Code-barres')}</label><input className="input tnum" value={f.code} onChange={fl('code')} inputMode="numeric" /></div>
        </div>
      </div>
      <div className="dr-sec">
        <div className="dr-label">{L('Contains allergens', 'Contient des allergènes')}</div>
        <div className="chips">{O.allergens.map(([k, n]) => <button key={k} className={'chip' + (f.al.includes(k) ? ' on' : '')} aria-pressed={f.al.includes(k)} onClick={() => setF({ ...f, al: f.al.includes(k) ? f.al.filter((x) => x !== k) : [...f.al, k] })}>{n[lang]}</button>)}</div>
        <span className="muted sm">{L('Allergens flow into the recipe allergen chart automatically.', 'Les allergènes alimentent automatiquement le tableau des recettes.')}</span>
      </div>
      <div className="dr-sec"><button className="btn btn-primary" onClick={save}><Icon n="floppy-disk" />{cur ? L('Save changes', 'Enregistrer') : L('Add ingredient', 'Ajouter')}</button></div>
    </div>
  );
}

function ScanModal({ open, onClose }) {
  const { L, lang, fmt, O, inv, setInv, ops, toast } = useMizo();
  const [code, setCode] = React.useState('');
  const [hit, setHit] = React.useState(null);
  const [qty, setQty] = React.useState('');
  const [list, setList] = React.useState([]);
  const [demo, setDemo] = React.useState(0);
  const byCode = (c) => inv.find((i) => (ops.meta[i.id] || [])[1] === c.trim());
  const look = (c) => { const i = byCode(c); setCode(c); setHit(i ? i.id : 'none'); setQty(i ? String(i.onHand) : ''); };
  const sim = () => { const pool = inv.filter((i) => (ops.meta[i.id] || [])[1]); const i = pool[demo % pool.length]; setDemo(demo + 1); look(ops.meta[i.id][1]); };
  const item = inv.find((i) => i.id === hit);
  const add = () => { if (!item || qty === '') return; setList([{ id: item.id, qty: Number(qty) }, ...list.filter((x) => x.id !== item.id)]); setHit(null); setCode(''); setQty(''); };
  const apply = () => { setInv(inv.map((i) => { const x = list.find((y) => y.id === i.id); return x ? { ...i, onHand: x.qty } : i; })); toast(L(`${list.length} counts saved`, `${list.length} quantités enregistrées`)); setList([]); onClose(); };
  return (
    <Modal open={open} onClose={onClose} wide title={<span className="wiz-title"><Icon n="barcode" />{L('Scan to count', 'Scanner pour compter')}</span>} actions={<>
      <span className="muted sm" style={{ marginRight: 'auto' }}>{list.length} {L('items scanned', 'articles scannés')}</span>
      <button className="btn btn-secondary" onClick={onClose}>{L('Close', 'Fermer')}</button>
      <button className="btn btn-primary" disabled={!list.length} onClick={apply}><Icon n="check-circle" />{L('Save counts', 'Enregistrer')}</button>
    </>}>
      <div className="grid-1-1">
        <div className="scan-col">
          <div className="scan-view"><i></i><span className="muted sm">{L('Camera preview — scanning uses your device camera in the mobile app (next phase).', 'Aperçu caméra — la caméra de l’appareil sera utilisée dans l’app mobile (prochaine phase).')}</span></div>
          <button className="btn btn-secondary" onClick={sim}><Icon n="scan" />{L('Simulate a scan', 'Simuler un scan')}</button>
          <form className="ask-row" onSubmit={(e) => { e.preventDefault(); look(code); }}><input className="input tnum" value={code} onChange={(e) => setCode(e.target.value)} placeholder={L('Or type a barcode', 'Ou tapez un code-barres')} inputMode="numeric" /><button className="btn btn-secondary">{L('Look up', 'Chercher')}</button></form>
        </div>
        <div className="scan-col">
          {item ? (
            <div className="panel" style={{ boxShadow: 'inset 0 0 0 1px var(--color-accent-800)' }}>
              <div className="card-kicker">{L('Found', 'Trouvé')} · {code}</div><h3>{item.name[lang]}</h3>
              <div className="muted sm">{L('System says', 'Système')} {fmt.num(item.onHand)} {item.unit} · {locName(O, (ops.meta[item.id] || [])[0], lang)}</div>
              <div className="field"><label>{L('Counted', 'Compté')} ({item.unit})</label><input className="input stepper-val" type="number" step="0.1" autoFocus value={qty} onChange={(e) => setQty(e.target.value)} /></div>
              <button className="btn btn-primary" onClick={add}><Icon n="plus" />{L('Add to count', 'Ajouter au compte')}</button>
            </div>
          ) : hit === 'none' ? <div className="suggest warnbox"><Icon n="warning" /><div>{L('No ingredient has this barcode. Add it in the ingredient database.', 'Aucun ingrédient avec ce code. Ajoutez-le à la base d’ingrédients.')}</div></div> : <div className="empty">{L('Scan or type a barcode to start.', 'Scannez ou tapez un code pour commencer.')}</div>}
          {list.length ? <div className="scan-list">{list.map((x) => { const i = inv.find((y) => y.id === x.id); const d = x.qty - i.onHand; return <div key={x.id} className="ln"><span>{i.name[lang]}</span><b>{fmt.num(x.qty)} {i.unit} <span className={d < 0 ? 'txt-neg' : d > 0 ? 'txt-pos' : 'muted'}>({d > 0 ? '+' : ''}{fmt.num(Math.round(d * 10) / 10)})</span></b></div>; })}</div> : null}
        </div>
      </div>
    </Modal>
  );
}

function Locations() {
  const { L, lang, fmt, O, inv, invMap, ops, upd, employees, toast } = useMizo();
  const [loc, setLoc] = React.useState('walkin');
  const [f, setF] = React.useState({ ing: 'chicken', from: 'walkin', to: 'line', qty: '', by: 'Nikos' });
  const at = (i, l) => locQty(i, ops)[l] || 0;
  const items = inv.filter((i) => at(i, loc) > 0);
  const avail = invMap[f.ing] ? at(invMap[f.ing], f.from) : 0;
  const ok = Number(f.qty) > 0 && Number(f.qty) <= avail && f.from !== f.to;
  const move = () => {
    const q = Number(f.qty), i = invMap[f.ing], prim = (ops.meta[f.ing] || [])[0];
    upd('locq', (lq) => { const cur = { ...(lq[f.ing] || {}) }; if (f.from !== prim) cur[f.from] = Math.max(0, (cur[f.from] || 0) - q); if (f.to !== prim) cur[f.to] = (cur[f.to] || 0) + q; return { ...lq, [f.ing]: cur }; });
    upd('transfers', (t) => [{ id: 'T' + Date.now(), date: TODAY, t: '14:20', ing: f.ing, qty: q, from: f.from, to: f.to, by: f.by }, ...t]);
    toast(L(`Moved ${q} ${i.unit} of ${i.name.en}`, `${q} ${i.unit} de ${i.name.fr} déplacé`)); setF({ ...f, qty: '' });
  };
  return (
    <div className="page">
      <PageHead sub={L('Where everything sits, and what moved between storage areas.', 'Où tout se trouve, et ce qui a bougé entre les zones.')} />
      <section className="loc-grid">
        {O.locations.map((l) => { const its = inv.filter((i) => at(i, l.id) > 0); return (
          <button key={l.id} className={'loc-card' + (loc === l.id ? ' on' : '')} onClick={() => setLoc(l.id)}>
            <span className="integ-ic"><Icon n={l.ic} s="1.3rem" /></span>
            <span className="loc-name">{l.name[lang]}</span><span className="muted sm">{typeof l.temp === 'string' ? l.temp : l.temp[lang]} · {its.length} {L('items', 'articles')}</span>
            <b className="tnum">{fmt.money0(its.reduce((s, i) => s + at(i, l.id) * i.cost, 0))}</b>
          </button>
        ); })}
      </section>
      <section className="grid-2-1">
        <div className="panel panel-flush">
          <div className="panel-head pad"><h3>{locName(O, loc, lang)}</h3></div>
          <div className="table-scroll">
            <table className="table mtable">
              <thead><tr><th>{L('Item', 'Article')}</th><th className="num">{L('Here', 'Ici')}</th><th className="num hide-sm">{L('Total on hand', 'Total')}</th><th className="num">{L('Value', 'Valeur')}</th></tr></thead>
              <tbody>{items.map((i) => <tr key={i.id}><td className="cell-main">{i.name[lang]}</td><td className="num tnum">{fmt.num(Math.round(at(i, loc) * 10) / 10)} <span className="muted">{i.unit}</span></td><td className="num tnum hide-sm">{fmt.num(i.onHand)}</td><td className="num tnum">{fmt.money(at(i, loc) * i.cost)}</td></tr>)}</tbody>
            </table>
          </div>
        </div>
        <div className="panel">
          <h3>{L('Move stock', 'Déplacer du stock')}</h3>
          <div className="form-grid">
            <div className="field span-2"><label>{L('Item', 'Article')}</label><select className="input" value={f.ing} onChange={(e) => setF({ ...f, ing: e.target.value })}>{inv.map((i) => <option key={i.id} value={i.id}>{i.name[lang]}</option>)}</select></div>
            <div className="field"><label>{L('From', 'De')}</label><select className="input" value={f.from} onChange={(e) => setF({ ...f, from: e.target.value })}>{O.locations.map((l) => <option key={l.id} value={l.id}>{l.name[lang]}</option>)}</select></div>
            <div className="field"><label>{L('To', 'Vers')}</label><select className="input" value={f.to} onChange={(e) => setF({ ...f, to: e.target.value })}>{O.locations.map((l) => <option key={l.id} value={l.id}>{l.name[lang]}</option>)}</select></div>
            <div className="field"><label>{L('Quantity', 'Quantité')} ({invMap[f.ing].unit})</label><input className="input" type="number" min="0" step="0.1" value={f.qty} onChange={(e) => setF({ ...f, qty: e.target.value })} /></div>
            <div className="field"><label>{L('Moved by', 'Par')}</label><select className="input" value={f.by} onChange={(e) => setF({ ...f, by: e.target.value })}>{employees.map((e) => <option key={e.id}>{e.name.split(' ')[0]}</option>)}</select></div>
          </div>
          <span className="muted sm">{fmt.num(Math.round(avail * 10) / 10)} {invMap[f.ing].unit} {L('available in', 'disponible dans')} {locName(O, f.from, lang)}</span>
          <button className="btn btn-primary" disabled={!ok} onClick={move} style={{ alignSelf: 'flex-start' }}><Icon n="arrows-left-right" />{L('Record transfer', 'Enregistrer le transfert')}</button>
        </div>
      </section>
      <div className="panel panel-flush">
        <div className="panel-head pad"><h3>{L('Recent transfers', 'Transferts récents')}</h3></div>
        <div className="table-scroll">
          <table className="table mtable">
            <thead><tr><th>{L('When', 'Quand')}</th><th>{L('Item', 'Article')}</th><th className="num">{L('Qty', 'Qté')}</th><th>{L('From → to', 'De → vers')}</th><th className="hide-sm">{L('By', 'Par')}</th></tr></thead>
            <tbody>{ops.transfers.map((t) => <tr key={t.id}><td className="tnum">{fmt.date(t.date, { weekday: 'short', day: 'numeric' })} · {t.t}</td><td className="cell-main">{invMap[t.ing].name[lang]}{t.note ? <div className="cell-sub">{t.note[lang]}</div> : null}</td><td className="num tnum">{fmt.num(t.qty)} {invMap[t.ing].unit}</td><td>{locName(O, t.from, lang)} → {locName(O, t.to, lang)}</td><td className="hide-sm">{t.by}</td></tr>)}</tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

function Expiry() {
  const { L, lang, fmt, O, inv, setInv, invMap, ops, upd, waste, setWaste, toast } = useMizo();
  const [f, setF] = React.useState('soon');
  const nm = (l) => (l.prep ? (O.prep.find((p) => p.id === l.prep) || {}).name[lang] + ' · ' + L('prep', 'prép.') : invMap[l.ing].name[lang]);
  const unit = (l) => l.unit || invMap[l.ing].unit;
  const all = ops.lots.slice().sort((a, b) => a.exp.localeCompare(b.exp));
  const rows = all.filter((l) => f === 'all' || daysTo(l.exp) <= 2);
  const atRisk = all.filter((l) => daysTo(l.exp) <= 2 && l.ing).reduce((s, l) => s + l.qty * invMap[l.ing].cost, 0);
  const discard = (l) => {
    upd('lots', (ls) => ls.filter((x) => x.id !== l.id));
    if (l.ing) { setInv(inv.map((i) => (i.id === l.ing ? { ...i, onHand: Math.max(0, i.onHand - l.qty) } : i))); setWaste([{ id: 'w' + Date.now(), date: TODAY, ing: l.ing, qty: l.qty, reason: 'expired', by: 'Eleni' }, ...waste]); }
    toast(L('Discarded and logged as waste', 'Jeté et noté en pertes'));
  };
  const tone = (d) => (d <= 0 ? 'neg' : d <= 2 ? 'warn' : 'pos');
  return (
    <div className="page">
      <PageHead sub={L('Every lot with a date on it — use the oldest first, and catch what’s about to turn.', 'Chaque lot daté — utilisez le plus vieux d’abord, et repérez ce qui va tourner.')}>
        <Seg size="sm" value={f} onChange={setF} options={[['soon', L('Next 2 days', '2 prochains jours')], ['all', L('All lots', 'Tous les lots')]]} />
      </PageHead>
      <section className="stats">
        <Stat label={L('Expire today', 'Expirent aujourd’hui')} value={all.filter((l) => daysTo(l.exp) <= 0).length} tone="neg">{L('Use or discard now', 'Utiliser ou jeter')}</Stat>
        <Stat label={L('Within 2 days', 'D’ici 2 jours')} value={all.filter((l) => daysTo(l.exp) > 0 && daysTo(l.exp) <= 2).length} tone="warn">{L('Put these first in line', 'À placer en premier')}</Stat>
        <Stat label={L('Value at risk', 'Valeur à risque')} value={fmt.money0(atRisk)}>{L('Ingredients only', 'Ingrédients seulement')}</Stat>
      </section>
      <div className="panel panel-flush">
        <div className="table-scroll">
          <table className="table mtable">
            <thead><tr><th>{L('Item', 'Article')}</th><th className="hide-sm">{L('Where', 'Où')}</th><th className="num">{L('Qty', 'Qté')}</th><th className="hide-sm">{L('Received', 'Reçu')}</th><th>{L('Use by', 'À utiliser avant')}</th><th></th></tr></thead>
            <tbody>{rows.map((l) => { const d = daysTo(l.exp); return (
              <tr key={l.id}>
                <td><div className="cell-main">{nm(l)} {l.first ? <span className="tag tag-accent">{L('Use first', 'En premier')}</span> : null}</div><div className="cell-sub">{L('Lot', 'Lot')} {l.id}</div></td>
                <td className="hide-sm">{locName(O, l.loc, lang)}</td><td className="num tnum">{fmt.num(l.qty)} <span className="muted">{unit(l)}</span></td><td className="tnum hide-sm">{fmt.date(l.recv)}</td>
                <td><Pill tone={tone(d)}>{d < 0 ? L('Expired', 'Expiré') : d === 0 ? L('Today', 'Aujourd’hui') : d === 1 ? L('Tomorrow', 'Demain') : fmt.date(l.exp, { weekday: 'short', month: 'short', day: 'numeric' })}</Pill></td>
                <td><div className="row-actions">{!l.first && d > 0 ? <button className="btn btn-ghost" onClick={() => upd('lots', (ls) => ls.map((x) => (x.id === l.id ? { ...x, first: true } : x)))}>{L('Use first', 'En premier')}</button> : null}<button className="btn btn-ghost" onClick={() => discard(l)}><Icon n="trash" />{L('Discard', 'Jeter')}</button></div></td>
              </tr>
            ); })}</tbody>
          </table>
          {!rows.length ? <div className="empty">{L('Nothing expiring soon.', 'Rien n’expire bientôt.')}</div> : null}
        </div>
      </div>
    </div>
  );
}

function Variance() {
  const { L, lang, fmt, O, inv, recipes } = useMizo();
  const theo = {}; recipes.forEach((r) => r.lines.forEach((l) => { theo[l.ing] = (theo[l.ing] || 0) + ((r.sold / 30) * 7) * l.qty; }));
  const cause = { potato: L('Over-prepping — see Waste', 'Surproduction — voir Pertes'), oliveoil: L('Free-pouring; try pour spouts', 'Versé à l’œil; essayez des becs verseurs'), spinach: L('Spoilage before use', 'Avarié avant usage'), feta: L('Heavy portions on salads', 'Portions généreuses sur les salades'), lamb: L('Dropped chops; trim loss', 'Côtelettes échappées; parage'), tomato: L('Spoilage + thick slicing', 'Avarié + tranches épaisses'), chicken: L('Portions over 160 g', 'Portions de plus de 160 g') };
  const rows = inv.filter((i) => theo[i.id]).map((i) => { const t = theo[i.id], a = t * (O.actualFactor[i.id] || 1); return { i, t, a, v: (a - t) * i.cost, p: ((a - t) / t) * 100 }; }).sort((x, y) => y.v - x.v);
  const T = rows.reduce((s, r) => s + r.t * r.i.cost, 0), A = rows.reduce((s, r) => s + r.a * r.i.cost, 0);
  return (
    <div className="page">
      <PageHead sub={L('Theoretical = what your recipes say you used, based on sales. Actual = last count + deliveries − this count. The gap is money leaving through waste, portioning or theft.', 'Théorique = ce que vos recettes disent d’après les ventes. Réel = dernier inventaire + livraisons − inventaire actuel. L’écart, c’est de l’argent perdu.')} />
      <section className="stats">
        <Stat label={L('Theoretical usage', 'Usage théorique')} value={fmt.money0(T)}>{L('Last 7 days', '7 derniers jours')}</Stat>
        <Stat label={L('Actual usage', 'Usage réel')} value={fmt.money0(A)}>{L('From counts and deliveries', 'Selon inventaires et livraisons')}</Stat>
        <Stat label={L('Variance', 'Écart')} value={fmt.money0(A - T)} tone="neg">{fmt.pct(((A - T) / T) * 100)} · {L('aim for under 2%', 'visez moins de 2 %')}</Stat>
        <Stat label={L('Yearly at this rate', 'Par année à ce rythme')} value={fmt.kmoney((A - T) * 52)} tone="neg">{L('If nothing changes', 'Si rien ne change')}</Stat>
      </section>
      <div className="panel panel-flush">
        <div className="table-scroll">
          <table className="table mtable">
            <thead><tr><th>{L('Item', 'Article')}</th><th className="num">{L('Theoretical', 'Théorique')}</th><th className="num">{L('Actual', 'Réel')}</th><th className="num">{L('Gap', 'Écart')}</th><th className="num">{L('Cost', 'Coût')}</th><th className="hide-md">{L('Likely cause', 'Cause probable')}</th></tr></thead>
            <tbody>{rows.map(({ i, t, a, v, p }) => (
              <tr key={i.id}><td className="cell-main">{i.name[lang]}</td><td className="num tnum">{fmt.num(Math.round(t * 10) / 10)} <span className="muted">{i.unit}</span></td><td className="num tnum">{fmt.num(Math.round(a * 10) / 10)}</td>
                <td className="num"><Pill tone={p > 8 ? 'neg' : p > 3 ? 'warn' : 'pos'}>{p >= 0 ? '+' : ''}{fmt.pct(p)}</Pill></td><td className="num tnum">{fmt.money(v)}</td><td className="muted hide-md">{p > 3 ? cause[i.id] || L('Check portions and waste log', 'Vérifier portions et pertes') : '—'}</td></tr>
            ))}</tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

function Movements() {
  const { L, lang, fmt, O, D, inv, setInv, invMap, pos, waste, ops, upd, recipes, toast } = useMizo();
  const [item, setItem] = React.useState('all');
  const [type, setType] = React.useState('all');
  const [adj, setAdj] = React.useState(null);
  const sup = (id) => D.suppliers.find((s) => s.id === id).name;
  let mv = [
    ...pos.filter((p) => p.status === 'received' || p.status === 'partial').flatMap((p) => p.lines.map(([ing, q]) => ({ d: p.expected, k: 'in', ing, q: p.status === 'partial' && ing === 'lamb' ? q - 3 : q, what: `${p.id} · ${sup(p.sup)}` }))),
    ...waste.map((w) => ({ d: w.date, k: 'waste', ing: w.ing, q: -w.qty, what: O.wasteReasons[w.reason][lang] + ' · ' + w.by })),
    ...ops.adj.map((a) => ({ d: a.date, k: 'adj', ing: a.ing, q: a.qty, what: O.adjReasons[a.reason][lang] + ' · ' + a.by + (a.note ? ' — ' + a.note[lang] : '') })),
    ...ops.transfers.map((t) => ({ d: t.date, k: 'move', ing: t.ing, q: 0, qq: t.qty, what: `${locName(O, t.from, lang)} → ${locName(O, t.to, lang)} · ${t.by}` })),
  ];
  if (item !== 'all') { const daily = recipes.reduce((s, r) => s + (r.sold / 30) * r.lines.filter((l) => l.ing === item).reduce((a, l) => a + l.qty, 0), 0); ['2026-10-28', '2026-10-27', '2026-10-26', '2026-10-25'].forEach((d) => mv.push({ d, k: 'sale', ing: item, q: -Math.round(daily * 10) / 10, what: L('Used by sales (from recipes)', 'Utilisé par les ventes (recettes)') })); }
  mv = mv.filter((m) => (item === 'all' || m.ing === item) && (type === 'all' || m.k === type) && invMap[m.ing]).sort((a, b) => b.d.localeCompare(a.d));
  const kl = { in: [L('Received', 'Reçu'), 'pos', 'truck'], waste: [L('Waste', 'Perte'), 'neg', 'trash'], adj: [L('Adjustment', 'Ajustement'), 'warn', 'sliders-horizontal'], move: [L('Transfer', 'Transfert'), 'neutral', 'arrows-left-right'], sale: [L('Sales', 'Ventes'), 'neutral', 'receipt'] };
  const save = () => {
    const q = Number(adj.qty) * (adj.dir === 'out' ? -1 : 1); if (!q) return;
    setInv(inv.map((i) => (i.id === adj.ing ? { ...i, onHand: Math.max(0, Math.round((i.onHand + q) * 100) / 100) } : i)));
    upd('adj', (a) => [{ id: 'A' + Date.now(), date: TODAY, ing: adj.ing, qty: q, reason: adj.reason, by: 'Eleni', note: adj.note ? { en: adj.note, fr: adj.note } : null }, ...a]);
    toast(L('Stock adjusted', 'Stock ajusté')); setAdj(null);
  };
  return (
    <div className="page">
      <PageHead sub={L('Every change to your stock — deliveries, waste, transfers and manual adjustments.', 'Chaque changement au stock — livraisons, pertes, transferts et ajustements.')}>
        <button className="btn btn-primary" onClick={() => setAdj({ ing: item === 'all' ? 'chicken' : item, dir: 'out', qty: '', reason: 'count', note: '' })}><Icon n="sliders-horizontal" />{L('Adjust stock', 'Ajuster le stock')}</button>
      </PageHead>
      <div className="panel panel-flush">
        <div className="toolbar">
          <select className="input" style={{ maxWidth: 260 }} value={item} onChange={(e) => setItem(e.target.value)}><option value="all">{L('All items', 'Tous les articles')}</option>{inv.map((i) => <option key={i.id} value={i.id}>{i.name[lang]}</option>)}</select>
          <Seg size="sm" value={type} onChange={setType} options={[['all', L('All', 'Tout')], ['in', kl.in[0]], ['waste', kl.waste[0]], ['adj', kl.adj[0]], ['move', kl.move[0]], ...(item !== 'all' ? [['sale', kl.sale[0]]] : [])]} />
          {item === 'all' ? <span className="muted sm">{L('Pick an item to also see daily sales usage', 'Choisissez un article pour voir l’usage par les ventes')}</span> : null}
        </div>
        <div className="table-scroll">
          <table className="table mtable">
            <thead><tr><th>{L('Date', 'Date')}</th><th>{L('Type', 'Type')}</th><th>{L('Item', 'Article')}</th><th className="hide-sm">{L('Details', 'Détails')}</th><th className="num">{L('Change', 'Variation')}</th></tr></thead>
            <tbody>{mv.map((m, i) => (
              <tr key={i}><td className="tnum">{fmt.date(m.d, { weekday: 'short', month: 'short', day: 'numeric' })}</td><td><Pill tone={kl[m.k][1]}><Icon n={kl[m.k][2]} /> {kl[m.k][0]}</Pill></td><td className="cell-main">{invMap[m.ing].name[lang]}</td><td className="hide-sm muted">{m.what}</td>
                <td className="num tnum">{m.k === 'move' ? <span className="muted">{fmt.num(m.qq)} {invMap[m.ing].unit}</span> : <span className={m.q > 0 ? 'txt-pos' : 'txt-neg'}>{m.q > 0 ? '+' : '−'}{fmt.num(Math.abs(m.q))} {invMap[m.ing].unit}</span>}</td></tr>
            ))}</tbody>
          </table>
          {!mv.length ? <div className="empty">{L('No movements.', 'Aucun mouvement.')}</div> : null}
        </div>
      </div>
      <Modal open={!!adj} onClose={() => setAdj(null)} title={L('Adjust stock', 'Ajuster le stock')} actions={<><button className="btn btn-secondary" onClick={() => setAdj(null)}>{L('Cancel', 'Annuler')}</button><button className="btn btn-primary" disabled={!adj || !Number(adj.qty)} onClick={save}>{L('Save adjustment', 'Enregistrer')}</button></>}>
        {adj ? <div className="form-grid">
          <div className="field span-2"><label>{L('Item', 'Article')}</label><select className="input" value={adj.ing} onChange={(e) => setAdj({ ...adj, ing: e.target.value })}>{inv.map((i) => <option key={i.id} value={i.id}>{i.name[lang]} · {fmt.num(i.onHand)} {i.unit}</option>)}</select></div>
          <div className="field"><label>{L('Direction', 'Sens')}</label><Seg size="sm" value={adj.dir} onChange={(v) => setAdj({ ...adj, dir: v })} options={[['out', L('Remove', 'Retirer')], ['in', L('Add', 'Ajouter')]]} /></div>
          <div className="field"><label>{L('Quantity', 'Quantité')} ({invMap[adj.ing].unit})</label><input className="input" type="number" min="0" step="0.1" value={adj.qty} onChange={(e) => setAdj({ ...adj, qty: e.target.value })} /></div>
          <div className="field span-2"><label>{L('Reason', 'Raison')}</label><select className="input" value={adj.reason} onChange={(e) => setAdj({ ...adj, reason: e.target.value })}>{Object.entries(O.adjReasons).map(([k, v]) => <option key={k} value={k}>{v[lang]}</option>)}</select></div>
          <div className="field span-2"><label>{L('Note (optional)', 'Note (facultatif)')}</label><input className="input" value={adj.note} onChange={(e) => setAdj({ ...adj, note: e.target.value })} /></div>
        </div> : null}
      </Modal>
    </div>
  );
}

Object.assign(window, { TODAY, daysTo, locName, locQty, AllergenTags, Ingredients, IngredientForm, ScanModal, Locations, Expiry, Variance, Movements });
