const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#9184d9",
  "density": "comfortable",
  "mode": "dark"
}/*EDITMODE-END*/;

function App() {
  const D = window.MIZO_DATA, O = window.MIZO_OPS;
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [lang, setLangS] = React.useState(() => localStorage.getItem('mizo.lang') || 'en');
  const [page, setPage] = React.useState(() => { const p = localStorage.getItem('mizo.page') || 'overview'; const a = SECTION_ALIAS[p]; const id = a ? a[0] : p; return SECTIONS.some((s) => s.id === id) ? id : 'overview'; });
  const [subs, setSubs] = React.useState(() => { try { return JSON.parse(localStorage.getItem('mizo.subs')) || {}; } catch (e) { return {}; } });
  const [focus, setFocus] = React.useState(null);
  const [inv, setInv] = React.useState(D.inventory);
  const [recipes, setRecipes] = React.useState(D.recipes);
  const [invoices, setInvoices] = React.useState(D.invoices);
  const [insightState, setInsightState] = React.useState({});
  const [target, setTarget] = React.useState(30);
  const [pos, setPos] = React.useState(O.pos);
  const [waste, setWaste] = React.useState(O.waste);
  const [fin, setFinS] = React.useState(() => { try { return JSON.parse(localStorage.getItem('mizo.fin')) || { p: 'month', c: 'prev' }; } catch (e) { return { p: 'month', c: 'prev' }; } });
  const setFin = (f) => { setFinS(f); localStorage.setItem('mizo.fin', JSON.stringify(f)); };
  const [calcD, setCalcD] = React.useState(null);
  const [ops, setOps] = React.useState(() => ({ meta: O.meta, locq: Object.fromEntries(D.inventory.filter((i) => O.meta[i.id] && O.meta[i.id][6]).map((i) => [i.id, { line: Math.round(i.onHand * O.meta[i.id][6] * 10) / 10 }])), lots: O.lots, transfers: O.transfers, adj: O.adjustments, returns: O.returns, scans: O.scans, supInfo: O.supInfo, recon: O.recon, subs: O.subs, tasks: O.tasks, notes: O.notes, equip: O.equipment, equipLog: O.equipLog, cooling: O.cooling, sanitizer: O.sanitizer }));
  const upd = (k, v) => setOps((s) => ({ ...s, [k]: typeof v === 'function' ? v(s[k]) : v }));
  const P = window.MIZO_PAY;
  const [employees, setEmployees] = React.useState(P.employees);
  const [punches, setPunches] = React.useState(() => P.genPunches());
  const [payStatus, setPayStatus] = React.useState('draft');
  const [now, setNow] = React.useState(P.NOW0);
  React.useEffect(() => { const t0 = Date.now(); const iv = setInterval(() => setNow(P.NOW0 + (Date.now() - t0) / 60000), 15000); return () => clearInterval(iv); }, []);
  const [importKind, setImportKind] = React.useState(null);
  const [toastMsg, setToastMsg] = React.useState(null);
  const toastT = React.useRef();
  const [prefs, setPrefsS] = React.useState(() => { try { return { text: 'normal', contrast: 'normal', motion: 'full', ...JSON.parse(localStorage.getItem('mizo.prefs')) }; } catch (e) { return { text: 'normal', contrast: 'normal', motion: 'full' }; } });
  const setPrefs = (p) => { const n = { ...prefs, ...p }; setPrefsS(n); localStorage.setItem('mizo.prefs', JSON.stringify(n)); };
  const [setup, setSetupS] = React.useState(() => { try { return { ...SETUP0, ...JSON.parse(localStorage.getItem('mizo.setup')) }; } catch (e) { return SETUP0; } });
  const setSetup = (s) => { setSetupS(s); localStorage.setItem('mizo.setup', JSON.stringify(s)); };
  const [wiz, setWiz] = React.useState(false);
  const [ui, setUi] = React.useState(null);
  const [tour, setTour] = React.useState(false);
  const [loc, setLocS] = React.useState(() => localStorage.getItem('mizo.loc') || 'parc');
  const setLoc = (l) => { setLocS(l); localStorage.setItem('mizo.loc', l); };
  const [locs, setLocs] = React.useState([]);
  const [addLoc, setAddLoc] = React.useState(false);
  const [exp, setExp] = React.useState(null);
  React.useEffect(() => { if (!setup.seen) { setWiz(true); setSetup({ ...setup, seen: true }); } }, []);
  React.useEffect(() => { const k = (e) => { const tag = (e.target.tagName || '').toLowerCase(); if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'k') { e.preventDefault(); setUi('search'); } else if (e.key === '/' && !['input', 'textarea', 'select'].includes(tag)) { e.preventDefault(); setUi('search'); } else if (e.key === '?' && e.shiftKey && !['input', 'textarea', 'select'].includes(tag)) setUi('help'); }; window.addEventListener('keydown', k); return () => window.removeEventListener('keydown', k); }, []);

  React.useEffect(() => {
    const h = document.documentElement;
    h.dataset.mode = t.mode; h.dataset.density = t.density; h.dataset.text = prefs.text; h.dataset.contrast = prefs.contrast; h.dataset.motion = prefs.motion; h.lang = lang === 'fr' ? 'fr-CA' : 'en-CA';
    h.style.setProperty('--color-accent', t.accent);
  }, [t.mode, t.density, t.accent, lang, prefs]);

  const setLang = (l) => { setLangS(l); localStorage.setItem('mizo.lang', l); };
  const setSub = (id, tb) => setSubs((s) => { const n = { ...s, [id]: tb }; localStorage.setItem('mizo.subs', JSON.stringify(n)); return n; });
  const go = (p, f) => {
    const a = SECTION_ALIAS[p], id = a ? a[0] : p;
    let tb = f && f.tab; if (!tb && f && f.item) tb = 'stock'; if (!tb && f && f.recipe) tb = 'recipes'; if (!tb && a) tb = a[1];
    setPage(id); setFocus(f || null); localStorage.setItem('mizo.page', id); if (tb) setSub(id, tb); window.scrollTo({ top: 0 });
  };
  const toast = (m) => { setToastMsg(m); clearTimeout(toastT.current); toastT.current = setTimeout(() => setToastMsg(null), 2600); };
  const invMap = React.useMemo(() => Object.fromEntries(inv.map((i) => [i.id, i])), [inv]);
  const L = (en, fr) => (lang === 'fr' ? fr : en);
  const fmt = React.useMemo(() => makeFmt(lang, setup.cur), [lang, setup.cur]);
  const openInsights = D.insights.filter((i) => !insightState[i.id]).length;
  const ctx = { L, lang, setLang, fmt, D, O, inv, setInv, invMap, recipes, setRecipes, invoices, setInvoices, insightState, setInsightState, target, setTarget, go, toast, P, employees, setEmployees, punches, setPunches, now, payStatus, setPayStatus, pos, setPos, waste, setWaste, ops, upd, fin, setFin, calc: setCalcD, F: window.MIZO_FIN, openImport: (k) => setImportKind(k || 'inventory'), prefs, setPrefs, setup, setSetup, openSetup: (st) => { if (st != null) setSetup({ ...setup, step: st }); setWiz(true); }, startTour: () => { go('overview', { tab: 'dashboard' }); setTimeout(() => setTour(true), 250); }, openHelp: () => setUi('help'), loc: loc === 'parc' || loc === 'all' || loc === 'laval' || locs.some((l) => l.id === loc) ? loc : 'parc', setLoc, locs, setLocs, openAddLoc: () => setAddLoc(true), openExport: (o) => setExp(o || { kind: 'pnl' }) };

  const intel = buildIntel(ctx);
  const sec = SECTIONS.find((s) => s.id === page) || SECTIONS[0];
  const tab = sec.tabs.some((x) => x[0] === subs[sec.id]) ? subs[sec.id] : sec.tabs[0][0];
  const setTab = (tb) => { setSub(sec.id, tb); setFocus(null); };
  const counts = {
    ai: { leaks: intel.open.length },
    purchasing: { approvals: pos.filter((p) => p.status === 'pending').length, scan: ops.scans.filter((s) => s.status === 'review').length, orders: pos.filter((p) => p.status === 'draft').length, receiving: pos.filter((p) => p.status === 'sent').length, invoices: invoices.filter((v) => v.status === 'overdue').length },
    team: { sheets: punches.filter((p) => p.flag === 'missing').length },
    inventory: { reorder: inv.filter((i) => stockState(i) !== 'ok').length, expiry: ops.lots.filter((l) => daysTo(l.exp) <= 1).length },
    sales: { recon: ops.recon.filter((r) => r.status === 'review').length },
  };
  const notifN = useAlertsCount(ctx);
  const railBadge = { ai: intel.open.length, purchasing: counts.purchasing.approvals + counts.purchasing.receiving };

  const S = {
    overview: { dashboard: <Overview2 />, alerts: <AlertsCenter />, activity: <Activity /> },
    inventory: { stock: <Inventory focus={focus && focus.item} startCount={focus && focus.count} />, ingredients: <Ingredients />, counts: <Counts />, locations: <Locations />, expiry: <Expiry />, waste: <Waste />, variance: <Variance />, movements: <Movements />, reorder: <Reorder /> },
    menu: { recipes: <Recipes focus={focus && focus.recipe} />, prep: <PrepRecipes />, yields: <Yields />, subs: <Substitutions />, allergens: <Allergens />, engineering: <MenuEngineering />, sim: <PriceSim />, pricing: <ChannelPricing /> },
    purchasing: { orders: <PurchaseOrders />, receiving: <Receiving focus={focus} />, invoices: <Suppliers focus={focus} tab="invoices" />, suppliers: <SupplierManager />, approvals: <Approvals />, returns: <Returns />, scan: <InvoiceScan />, prices: <Suppliers focus={focus} tab="prices" /> },
    sales: { summary: <SalesSummary />, mix: <ProductMix />, channels: <Channels />, delivery: <DeliveryApps />, recon: <Reconciliation />, tickets: <Tickets />, payments: <Payments />, pos: <PosSetup /> },
    team: { schedule: <Schedule />, clock: <Payroll tab="clock" setTab={setTab} />, sheets: <Payroll tab="sheets" setTab={setTab} />, run: <Payroll tab="run" setTab={setTab} />, team: <Payroll tab="team" setTab={setTab} />, tasks: <Checklists />, labour: <Labour />, todo: <StaffTasks />, safety: <FoodSafety />, equipment: <Equipment />, log: <ManagerLog /> },
    finance: { summary: <FinSummary />, pnl: <FinPnL />, revenue: <FinRevenue />, costs: <FinCosts />, foodbev: <FinFoodBev />, labour: <FinLabour />, prime: <FinPrime />, inventory: <FinInvWaste />, suppliers: <FinSuppliers />, menu: <FinMenu />, cash: <CashFlow />, ap: <FinAP />, budget: <Budget />, forecast: <FinForecast />, bench: <FinBench />, locations: <FinLocations /> },
    ai: { ask: <Assistant />, leaks: <ProfitLeaks />, suggestions: <Recommendations />, health: <HealthScore />, simulate: <Simulator />, briefings: <Briefings />, buying: <SmartOrdering />, forecast: <Forecasts />, automations: <Automations /> },
    settings: { general: <Settings part="general" />, users: <UsersRoles />, integrations: <Settings part="integrations" />, notifications: <Notifications /> },
  };
  const quick = [
    ['clipboard-text', L('Count inventory', 'Compter l’inventaire'), () => go('inventory', { tab: 'counts' })],
    ['trash', L('Log waste', 'Noter des pertes'), () => go('inventory', { tab: 'waste' })],
    ['file-plus', L('New purchase order', 'Nouveau bon de commande'), () => go('purchasing', { tab: 'orders' })],
    ['truck', L('Receive a delivery', 'Recevoir une livraison'), () => go('purchasing', { tab: 'receiving' })],
    ['scan', L('Scan an invoice', 'Numériser une facture'), () => go('purchasing', { tab: 'scan' })],
    ['microsoft-excel-logo', L('Import from Excel', 'Importer depuis Excel'), () => setImportKind('inventory')],
    ['printer', L('Print or export a report (PDF)', 'Imprimer ou exporter un rapport (PDF)'), () => setExp({ kind: 'pnl' })],
    ['buildings', L('Switch location', 'Changer de restaurant'), () => setTimeout(() => { const b = document.querySelector('.locsw-btn'); if (b) b.click(); }, 50)],
    ['clock', L('Approve timesheets', 'Approuver les heures'), () => go('team', { tab: 'sheets' })],
    ['sparkle', L('Ask MIZO a question', 'Poser une question à MIZO'), () => go('ai', { tab: 'ask' })],
    ['drop-half-bottom', L('See profit leaks', 'Voir les fuites de profit'), () => go('ai', { tab: 'leaks' })],
    ['list-checks', L('Open the setup guide', 'Ouvrir le guide de configuration'), () => ctx.openSetup()],
    ['compass', L('Take the product tour', 'Faire la visite guidée'), () => ctx.startTour()],
    ['text-aa', prefs.text === 'normal' ? L('Make text larger', 'Agrandir le texte') : L('Make text normal size', 'Texte de taille normale'), () => setPrefs({ text: prefs.text === 'normal' ? 'large' : 'normal' })],
    ['translate', lang === 'en' ? 'Passer au français' : 'Switch to English', () => setLang(lang === 'en' ? 'fr' : 'en')],
  ].map(([ic, t, run]) => ({ ic, t, run }));
  const railBtn = (s) => (
    <button key={s.id} data-sec={s.id} className={'rail-item' + (page === s.id ? ' on' : '')} onClick={() => go(s.id)} aria-current={page === s.id ? 'page' : undefined} title={L(...s.t)}>
      <Icon n={s.ic} />{L(...s.s)}
      {railBadge[s.id] ? <span className="badge">{railBadge[s.id]}</span> : null}
    </button>
  );

  return (
    <MizoCtx.Provider value={ctx}>
      <div className="app">
        <nav className="rail" aria-label="Main">
          <button className="logo" aria-label="MIZO" onClick={() => go('overview')} style={{ border: 0, cursor: 'pointer' }}></button>
          {SECTIONS.filter((s) => s.id !== 'settings').map(railBtn)}
          <button className={'rail-item rail-more' + (['purchasing', 'sales', 'team', 'finance', 'ai', 'settings'].includes(page) ? ' on' : '')} onClick={() => setUi('more')}><Icon n="dots-three-circle" />{L('More', 'Plus')}{railBadge.ai || railBadge.purchasing ? <span className="badge">{(railBadge.ai || 0) + (railBadge.purchasing || 0)}</span> : null}</button>
          <div className="rail-spacer"></div>
          {railBtn(SECTIONS.find((s) => s.id === 'settings'))}
        </nav>
        <div className="main">
          <header className="topbar">
            <LocationSwitcher />
            <button className="tsearch" onClick={() => setUi('search')} aria-label={L('Search or jump to', 'Rechercher ou aller à')}><Icon n="magnifying-glass" /><span>{L('Search or do something…', 'Rechercher ou faire…')}</span><kbd>Ctrl K</kbd></button>
            <button className="btn btn-icon btn-secondary" onClick={() => go('ai', { tab: 'ask' })} aria-label={L('Ask MIZO', 'Demandez à MIZO')} title={L('Ask MIZO', 'Demandez à MIZO')}><Icon n="sparkle" /></button>
            <button className="btn btn-icon btn-secondary tbell" onClick={() => setUi('notif')} aria-label={L('Notifications', 'Notifications')} title={L('Notifications', 'Notifications')}><Icon n="bell-simple" />{notifN ? <span className="badge">{notifN}</span> : null}</button>
            <button className="btn btn-secondary thelp" onClick={() => setUi('help')} aria-label={L('Help', 'Aide')}><Icon n="question" /><span>{L('Help', 'Aide')}</span></button>
            <div className="lang" role="group" aria-label="Language">
              <button className={lang === 'en' ? 'on' : ''} onClick={() => setLang('en')}>EN</button>
              <button className={lang === 'fr' ? 'on' : ''} onClick={() => setLang('fr')}>FR</button>
            </div>
            <div className="avatar" title={D.restaurant.ownerFull}>EP</div>
          </header>
          <main className="content" key={page + lang} data-screen-label={L(...sec.t)}>
            <SectionCtx.Provider value={true}>
              <div className="sec">
                <SectionHead sec={sec} tab={tab} setTab={setTab} title={page === 'overview' ? `Kaliméra, ${D.restaurant.owner}` : null} counts={counts[sec.id]} />
                <div key={tab} className="sec-body">{sec.id !== 'settings' ? <LocBanner sec={sec.id} /> : null}{S[sec.id][tab]}</div>
              </div>
            </SectionCtx.Provider>
          </main>
        </div>
      </div>
      <Drawer open={!!calcD} onClose={() => setCalcD(null)}>{calcD ? <CalcView d={calcD} /> : null}</Drawer>
      <Drawer open={ui === 'help' || ui === 'notif'} onClose={() => setUi(null)}>{ui === 'help' ? <HelpPanel secId={page} onClose={() => setUi(null)} onTour={() => { setUi(null); ctx.startTour(); }} onSetup={() => { setUi(null); setSetup({ ...setup, hide: false }); setWiz(true); }} /> : ui === 'notif' ? <NotifPanel onClose={() => setUi(null)} /> : null}</Drawer>
      <CommandPalette open={ui === 'search'} onClose={() => setUi(null)} actions={quick} />
      <MoreSheet open={ui === 'more'} onClose={() => setUi(null)} page={page} badges={railBadge} />
      <SetupWizard open={wiz} onClose={() => setWiz(false)} onTour={ctx.startTour} />
      <Tour open={tour} onClose={(fin) => { setTour(false); if (fin) toast(L('Tour finished — Help is always at the top right', 'Visite terminée — l’Aide est toujours en haut à droite')); }} />
      <ExportDialog open={!!exp} init={exp} onClose={() => setExp(null)} />
      <AddLocationModal open={addLoc} onClose={() => setAddLoc(false)} />
      <ImportWizard open={!!importKind} kind={importKind} onClose={() => setImportKind(null)} />
      <div className={'toast' + (toastMsg ? ' show' : '')} role="status" aria-live="polite"><Icon n="check-circle" />{toastMsg}</div>
      <TweaksPanel>
        <TweakSection label="Theme" />
        <TweakRadio label="Mode" value={t.mode} options={['dark', 'light']} onChange={(v) => setTweak('mode', v)} />
        <TweakColor label="Accent" value={t.accent} options={['#9184d9', '#6f9be0', '#8fb07a', '#d9906a', '#d4b05e']} onChange={(v) => setTweak('accent', v)} />
        <TweakSection label="Layout" />
        <TweakRadio label="Density" value={t.density} options={['compact', 'comfortable', 'large']} onChange={(v) => setTweak('density', v)} />
      </TweaksPanel>
    </MizoCtx.Provider>
  );
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
