const IA_SUGG = [
  ['profit', 'Why did my profit decrease this week?', 'Pourquoi mon profit a-t-il baissé cette semaine?'],
  ['menu', 'What are my most profitable menu items?', 'Quels sont mes plats les plus rentables?'],
  ['supplier', 'Which suppliers increased their prices?', 'Quels fournisseurs ont augmenté leurs prix?'],
  ['order', 'How much inventory should I order?', 'Combien d’inventaire dois-je commander?'],
  ['improve', 'What can I do to improve profitability?', 'Comment améliorer ma rentabilité?'],
  ['waste', 'Which ingredients are being wasted?', 'Quels ingrédients sont gaspillés?'],
  ['price', 'Should I increase my menu prices?', 'Dois-je augmenter mes prix?'],
];
function iaIntent(t) {
  const s = t.toLowerCase();
  if (/supplier|fournisseur|vendor/.test(s)) return 'supplier';
  if (/raise|increase my menu|menu price|augmenter (mes|les) prix|hausser|prix du menu/.test(s)) return 'price';
  if (/improve|améliorer|ameliorer|leak|fuite|save money|économiser/.test(s)) return 'improve';
  if (/profit|bénéfice/.test(s) && /week|semaine|decreas|drop|down|baiss|why|pourquoi/.test(s)) return 'profit';
  if (/dish|plat|menu item|best seller|profitable|rentable/.test(s)) return 'menu';
  if (/order|commander|reorder|buy|acheter|inventory should/.test(s)) return 'order';
  if (/wast|perte|gaspill|throw|jet/.test(s)) return 'waste';
  return 'help';
}

function IaDrivers({ items, fmt }) {
  const mx = Math.max(1, ...items.map((x) => Math.abs(x.v)));
  return <div className="sim-eff">{items.map((x) => <div key={x.n} className="sim-eff-row"><span>{x.n}</span><span className="sim-eff-track"><i className={x.v < 0 ? 'neg' : 'pos'} style={{ width: (Math.abs(x.v) / mx) * 50 + '%', [x.v < 0 ? 'right' : 'left']: '50%' }}></i></span><b className={'tnum ' + (x.v < 0 ? 'txt-neg' : 'txt-pos')}>{x.v >= 0 ? '+' : '−'}{fmt.money0(Math.abs(x.v))}</b></div>)}</div>;
}
function IaTable({ head, body }) {
  return <div className="table-scroll"><table className="table mtable calc-table"><thead><tr>{head.map((h, i) => <th key={i} className={i ? 'num' : ''}>{h}</th>)}</tr></thead><tbody>{body.map((r, i) => <tr key={i}>{r.map((v, j) => <td key={j} className={j ? 'num tnum' : 'cell-main'}>{v}</td>)}</tr>)}</tbody></table></div>;
}

function iaAnswer(intent, c, I) {
  const { L, lang, fmt, F, O, D, recipes, invMap, go, target, calc } = c;
  const m = fmt.money0, A = (label, to, ic) => ({ label, ic: ic || 'arrow-right', fn: () => go(to[0], { tab: to[1] }) });
  if (intent === 'profit') {
    const cur = F.days.filter((x) => x.d >= '2026-10-26' && x.d <= '2026-10-27'), prv = F.days.filter((x) => x.d >= '2026-10-19' && x.d <= '2026-10-20');
    const a = finK(fsum(cur)), b = finK(fsum(prv)), d = a.op - b.op;
    const drv = [{ n: L('Sales', 'Ventes'), v: a.rev - b.rev }, { n: L('Cost of goods', 'Marchandises'), v: -(a.cogs - b.cogs) }, { n: L('Labour', 'Main-d’œuvre'), v: -(a.lab - b.lab) }, { n: L('Fees & fixed costs', 'Frais et coûts fixes'), v: -(a.opx - b.opx) }];
    const worst = drv.slice().sort((x, y) => x.v - y.v)[0];
    return { text: [d < 0 ? L(`Estimated operating profit for Monday–Tuesday is ${m(a.op)}, ${m(Math.abs(d))} lower than the same two days last week (${m(b.op)}).`, `Le profit d’exploitation estimé pour lundi–mardi est de ${m(a.op)}, ${m(Math.abs(d))} de moins que les mêmes jours la semaine dernière (${m(b.op)}).`) : L(`It didn’t decrease — Monday–Tuesday operating profit is an estimated ${m(a.op)}, ${m(d)} higher than the same two days last week.`, `Il n’a pas baissé — le profit estimé lundi–mardi est de ${m(a.op)}, ${m(d)} de plus que la semaine dernière.`), L(`The biggest driver is ${worst.n.toLowerCase()} (${worst.v >= 0 ? '+' : '−'}${m(Math.abs(worst.v))}). Labour was ${fmt.pct(a.labPct)} of sales vs ${fmt.pct(b.labPct)}; food cost ${fmt.pct(a.foodPct)} vs ${fmt.pct(b.foodPct)}.`, `Le principal facteur : ${worst.n.toLowerCase()} (${worst.v >= 0 ? '+' : '−'}${m(Math.abs(worst.v))}). Main-d’œuvre ${fmt.pct(a.labPct)} des ventes vs ${fmt.pct(b.labPct)}; coût alimentaire ${fmt.pct(a.foodPct)} vs ${fmt.pct(b.foodPct)}.`), L('Today isn’t closed yet, so it’s left out. Daily costs are allocated from monthly totals.', 'Aujourd’hui n’est pas fermé, donc exclu. Les coûts quotidiens sont répartis des totaux mensuels.')],
      viz: <><div className="dr-label">{L('Change in operating profit, by driver', 'Écart du profit d’exploitation, par facteur')}</div><IaDrivers items={drv} fmt={fmt} /></>, prov: 'e', sources: [L('POS daily sales', 'Ventes PDV'), L('Time clock', 'Pointage'), L('Invoices', 'Factures')], actions: [A(L('Open profit & loss', 'Ouvrir l’état des résultats'), ['finance', 'pnl']), A(L('See profit leaks', 'Voir les fuites'), ['ai', 'leaks'])] };
  }
  if (intent === 'menu') {
    const rows = recipes.map((r) => ({ r, c: recipeCost(r, invMap) })).sort((x, y) => y.c.monthly - x.c.monthly), low = rows.slice().sort((x, y) => x.c.margin / x.r.price - y.c.margin / y.r.price)[0];
    return { text: [L(`${rows[0].r.name.en} earns the most: ${m(rows[0].c.monthly)} a month after food cost, from ${fmt.num(rows[0].r.sold)} sold at ${fmt.money(rows[0].c.margin)} each. Volume, not margin, drives it.`, `${rows[0].r.name.fr} rapporte le plus : ${m(rows[0].c.monthly)} par mois après coût des aliments, ${fmt.num(rows[0].r.sold)} vendus à ${fmt.money(rows[0].c.margin)} chacun. C’est le volume qui compte.`), L(`${low.r.name.en} has the thinnest margin (${fmt.pct(low.c.fc)} food cost).`, `${low.r.name.fr} a la marge la plus mince (${fmt.pct(low.c.fc)} de coût).`), L('This is profit after food and packaging only — labour and rent are not taken off per dish.', 'Profit après aliments et emballage seulement — ni main-d’œuvre ni loyer par plat.')],
      viz: <HBars items={rows.slice(0, 5).map(({ r, c: cc }) => ({ label: r.name[lang], v: cc.monthly, sub: `${fmt.num(r.sold)} · ${fmt.money(cc.margin)} ${L('per plate', 'par assiette')} · ${fmt.pct(cc.fc)}` }))} fmtv={m} />, prov: 'e', sources: [L('Recipes', 'Recettes'), L('POS item sales', 'Ventes par article'), L('Latest invoice prices', 'Derniers prix facturés')], actions: [A(L('Menu engineering', 'Ingénierie du menu'), ['menu', 'engineering'])] };
  }
  if (intent === 'supplier') {
    const rows = c.inv.map((i) => ({ i, r: (i.cost / i.hist[0] - 1) * 100 })).filter((x) => x.r >= 3).sort((a, b) => b.r - a.r);
    const sups = [...new Set(rows.map((x) => x.i.sup))].map((id) => D.suppliers.find((s) => s.id === id).name);
    return { text: [L(`${sups.length} suppliers raised prices over six months: ${sups.join(', ')}.`, `${sups.length} fournisseurs ont augmenté leurs prix en six mois : ${sups.join(', ')}.`), L(`${rows[0].i.name.en} (+${fmt.pct(rows[0].r)}) and ${rows[1].i.name.en.toLowerCase()} lead. Switching ${I.q.map((x) => x.i.name.en.toLowerCase()).join(', ')} to same-spec quotes saves about ${m(I.q.reduce((s, x) => s + x.save, 0))} a month.`, `${rows[0].i.name.fr} (+${fmt.pct(rows[0].r)}) et ${rows[1].i.name.fr.toLowerCase()} en tête. Passer ${I.q.map((x) => x.i.name.fr.toLowerCase()).join(', ')} aux offres équivalentes économise environ ${m(I.q.reduce((s, x) => s + x.save, 0))} par mois.`)],
      viz: <IaTable head={[L('Ingredient', 'Ingrédient'), L('Supplier', 'Fournisseur'), L('6 mo ago', 'Il y a 6 mois'), L('Now', 'Actuel'), L('Change', 'Écart')]} body={rows.slice(0, 6).map((x) => [x.i.name[lang], D.suppliers.find((s) => s.id === x.i.sup).name.split(' ')[0], fmt.money(x.i.hist[0]), fmt.money(x.i.cost), '+' + fmt.pct(x.r)])} />, prov: 'v', sources: [L('Invoice line prices', 'Prix des factures'), L('Supplier quotes', 'Soumissions')], actions: [A(L('Price comparison', 'Comparer les prix'), ['purchasing', 'prices'])] };
  }
  if (intent === 'order') {
    const R = intelOrders(c, I);
    return { text: [L(`Based on the 7-day forecast and what’s on the shelf, order about ${m(R.bySup.reduce((s, g) => s + g.total, 0))} across ${R.bySup.length} suppliers.`, `Selon la prévision sur 7 jours et le stock, commandez environ ${m(R.bySup.reduce((s, g) => s + g.total, 0))} chez ${R.bySup.length} fournisseurs.`), L(`${R.covered.length} items are already covered, including what’s on PO-1049. Perishables are capped by shelf life.`, `${R.covered.length} articles sont déjà couverts, dont ce qui est sur le BC-1049. Les périssables sont plafonnés.`)],
      viz: <IaTable head={[L('Supplier', 'Fournisseur'), L('Delivery', 'Livraison'), L('Items', 'Articles'), L('Total', 'Total')]} body={R.bySup.map((g) => [g.s.name, fmt.date(g.exp, { weekday: 'short', day: 'numeric' }), g.lines.map((x) => x.i.name[lang].split(' ')[0]).join(', '), fmt.money0(g.total)])} />, prov: 'e', sources: [L('Stock on hand', 'Stock'), L('Sales forecast', 'Prévision'), L('Recipes', 'Recettes'), L('Supplier schedules', 'Horaires fournisseurs')], actions: [A(L('Open smart ordering', 'Ouvrir la commande intelligente'), ['ai', 'buying'], 'shopping-cart')] };
  }
  if (intent === 'improve') {
    const top = I.open.slice().sort((a, b) => b.impact - a.impact).slice(0, 4);
    return { text: [L(`MIZO sees ${m(I.openTotal)} a month in open profit leaks. The four biggest cover ${m(top.reduce((s, x) => s + x.impact, 0))}:`, `MIZO voit ${m(I.openTotal)} par mois de fuites ouvertes. Les quatre plus grosses représentent ${m(top.reduce((s, x) => s + x.impact, 0))} :`)],
      viz: <ul className="ai-list">{top.map((x) => <li key={x.id}><span className="ai-amt">{m(x.impact)}</span><span>{x.action} — <span className="muted">{x.title}</span></span></li>)}</ul>, prov: 'e', sources: [L('Profit leak detector', 'Détecteur de fuites')], actions: [A(L('Open profit leaks', 'Ouvrir les fuites'), ['ai', 'leaks']), A(L('Recommendations', 'Recommandations'), ['ai', 'suggestions'])], post: L('Fixing the verified ones first (supplier prices, duplicates, billing) needs no change in the kitchen.', 'Commencez par les fuites vérifiées (prix, doublons, facturation) : aucun changement en cuisine.') };
  }
  if (intent === 'waste') {
    return { text: [L(`Logged waste is running about ${m(I.wMonthly)} a month; ${m(I.wAvoidM)} of that is avoidable. Most of it is over-prepped potatoes early in the week, then dropped lamb and spoiled feta.`, `Les pertes consignées sont d’environ ${m(I.wMonthly)} par mois, dont ${m(I.wAvoidM)} évitables. Surtout des pommes de terre trop préparées en début de semaine, puis agneau échappé et feta avariée.`)],
      viz: <HBars items={I.wRows.slice(0, 6).map(([id, x]) => ({ label: invMap[id].name[lang], v: x.v, sub: `${fmt.num(Math.round(x.q * 10) / 10)} ${invMap[id].unit} · ${Object.keys(x.r).map((r) => O.wasteReasons[r][lang]).join(', ')}` }))} fmtv={fmt.money} />, prov: 'v', sources: [L('Waste log', 'Journal des pertes')], actions: [A(L('Open waste log', 'Ouvrir les pertes'), ['inventory', 'waste'])], post: L('Unlogged waste shows up as count variance instead — see Inventory discrepancies.', 'Les pertes non consignées apparaissent comme écarts d’inventaire.') };
  }
  if (intent === 'price') {
    const rows = recipes.map((r) => ({ r, c: recipeCost(r, invMap) })).sort((a, b) => b.c.fc - a.c.fc);
    const hi = rows.filter((x) => x.c.fc > target + 3);
    return { text: [hi.length ? L(`Not across the board. Only ${hi.map((x) => x.r.name.en).join(', ')} ${hi.length > 1 ? 'are' : 'is'} well above your ${target}% target; most dishes are at or under it.`, `Pas partout. Seul(s) ${hi.map((x) => x.r.name.fr).join(', ')} dépasse(nt) nettement la cible de ${target} %; la plupart des plats sont dans la cible.`) : L('Your dishes are within target — a general increase isn’t needed.', 'Vos plats respectent la cible — pas besoin de hausse générale.'), I.pr.length ? L(`Raising ${I.pr[0].r.name.en} to ${fmt.money(I.pr[0].np)} adds about ${m(I.pr[0].v)} a month if orders hold. Try it with lower volume in the simulator first.`, `Passer ${I.pr[0].r.name.fr} à ${fmt.money(I.pr[0].np)} ajoute environ ${m(I.pr[0].v)} par mois si les ventes tiennent. Testez d’abord dans le simulateur.`) : null].filter(Boolean),
      viz: <IaTable head={[L('Dish', 'Plat'), L('Price', 'Prix'), L('Food cost', 'Coût'), L('vs target', 'vs cible')]} body={rows.slice(0, 5).map((x) => [x.r.name[lang], fmt.money(x.r.price), fmt.pct(x.c.fc), (x.c.fc - target >= 0 ? '+' : '−') + fmt.num(Math.abs(Math.round((x.c.fc - target) * 10) / 10)) + ' pts'])} />, prov: 'e', sources: [L('Recipes', 'Recettes'), L('Invoice prices', 'Prix facturés')], actions: [A(L('Open simulator', 'Ouvrir le simulateur'), ['ai', 'simulate'], 'sliders-horizontal'), A(L('Menu price simulator', 'Simulateur de prix'), ['menu', 'sim'])] };
  }
  return { text: [L('In this demo I can answer questions about profit, dishes, suppliers, ordering, waste and pricing, using Souvlaki Village’s sample data. Try one of these:', 'Dans cette démo, je réponds sur le profit, les plats, les fournisseurs, les commandes, les pertes et les prix, avec les données d’exemple. Essayez :')], viz: null, prov: null, sources: [], actions: [], chips: true };
}

function Assistant() {
  const c = useMizo(); const { L, lang } = c;
  const I = useIntel();
  const [chat, setChat] = React.useState(() => { try { return JSON.parse(sessionStorage.getItem('mizo.ia')) || []; } catch (e) { return []; } });
  const [q, setQ] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const end = React.useRef(null);
  React.useEffect(() => { sessionStorage.setItem('mizo.ia', JSON.stringify(chat)); const el = end.current; if (el && el.parentNode) el.parentNode.scrollTop = el.parentNode.scrollHeight; }, [chat, busy]);
  const ask = (t, key) => { const text = (t || q).trim(); if (!text || busy) return; setQ(''); setChat((x) => [...x, { who: 'me', t: text }]); setBusy(true); setTimeout(() => { setChat((x) => [...x, { who: 'ai', intent: key || iaIntent(text) }]); setBusy(false); }, 650 + Math.random() * 450); };
  const srcs = [[L('POS sales · 58 days', 'Ventes PDV · 58 jours'), 'v'], [L('Supplier invoices', 'Factures fournisseurs'), 'v'], [L('Recipes & plate costs', 'Recettes et coûts'), 'e'], [L('Waste log', 'Journal des pertes'), 'v'], [L('Time clock (unapproved)', 'Pointage (non approuvé)'), 'e'], [L('Sales forecast', 'Prévision'), 'e'], [L('Owner pay, insurance', 'Rémunération, assurances'), 'm']];
  return (
    <div className="page">
      <PageHead sub={L('Ask about your restaurant in plain words. Answers use your own numbers and show where they came from.', 'Posez vos questions simplement. Les réponses utilisent vos chiffres et en montrent la source.')}><SimTag /></PageHead>
      <section className="grid-2-1">
        <div className="panel ask ia">
          <Meander />
          <div className="ai-kicker"><Icon n="sparkle" />MIZO {L('Assistant', 'Assistant')}</div>
          {chat.length ? <div className="ia-chat">
            {chat.map((x, i) => { if (x.who === 'me') return <div key={i} className="msg me">{x.t}</div>; const a = iaAnswer(x.intent, c, I); return (
              <div key={i} className="msg ai ia-ans">
                {a.text.map((p, j) => <p key={j}>{p}</p>)}
                {a.viz ? <div className="ia-viz">{a.viz}</div> : null}
                {a.post ? <p className="muted">{a.post}</p> : null}
                {a.chips ? <div className="chips">{IA_SUGG.map(([k, en, fr]) => <button key={k} className="chip" onClick={() => ask(L(en, fr), k)}>{L(en, fr)}</button>)}</div> : null}
                {a.actions.length ? <div className="ia-acts">{a.actions.map((b) => <button key={b.label} className="btn btn-secondary" onClick={b.fn}><Icon n={b.ic} />{b.label}</button>)}</div> : null}
                {a.prov ? <div className="ia-foot"><Prov k={a.prov} /><span>{L('From', 'Source')} : {a.sources.join(' · ')}</span><span className="ia-sim">{L('Simulated response', 'Réponse simulée')}</span></div> : null}
              </div>
            ); })}
            {busy ? <div className="msg ai typing"><span></span><span></span><span></span></div> : null}
            <div ref={end}></div>
          </div> : <><h2 className="ai-headline">{L('Where am I losing money, and what should I do about it?', 'Où est-ce que je perds de l’argent, et que faire?')}</h2><p className="muted" style={{ margin: 0 }}>{L('Pick a question to start, or type your own.', 'Choisissez une question ou écrivez la vôtre.')}</p><div className="chips">{IA_SUGG.map(([k, en, fr]) => <button key={k} className="chip" onClick={() => ask(L(en, fr), k)}>{L(en, fr)}</button>)}</div></>}
          <form className="ask-row" onSubmit={(e) => { e.preventDefault(); ask(); }}>
            <input className="input" value={q} onChange={(e) => setQ(e.target.value)} placeholder={L('e.g. Which suppliers increased their prices?', 'ex. Quels fournisseurs ont augmenté leurs prix?')} aria-label={L('Ask MIZO', 'Demandez à MIZO')} />
            <button className="btn btn-primary" disabled={busy || !q.trim()}><Icon n="paper-plane-right" />{L('Ask', 'Demander')}</button>
            {chat.length ? <button type="button" className="btn btn-ghost btn-icon" onClick={() => setChat([])} aria-label={L('New conversation', 'Nouvelle conversation')} title={L('New conversation', 'Nouvelle conversation')}><Icon n="arrow-counter-clockwise" /></button> : null}
          </form>
        </div>
        <div className="ia-side">
          <div className="panel">
            <h3>{L('Suggested questions', 'Questions suggérées')}</h3>
            <div className="ia-qs">{IA_SUGG.map(([k, en, fr]) => <button key={k} className="ia-q" onClick={() => ask(L(en, fr), k)} disabled={busy}><Icon n="chat-circle-text" />{L(en, fr)}</button>)}</div>
          </div>
          <div className="panel">
            <h3>{L('What MIZO is reading', 'Ce que MIZO consulte')}</h3>
            {srcs.map(([n, p]) => <div key={n} className="ln"><span>{n}</span><Prov k={p} /></div>)}
            <p className="muted sm" style={{ margin: 0 }}>{L('Phase 1 answers are simulated from demo data. A live model connects in Phase 2 — the questions, sources and actions stay the same.', 'En phase 1, les réponses sont simulées. Un modèle réel se connecte en phase 2 — questions, sources et actions restent les mêmes.')}</p>
          </div>
        </div>
      </section>
    </div>
  );
}

Object.assign(window, { IA_SUGG, iaIntent, iaAnswer, Assistant });
