/* app.jsx — flow state machine, kiosk frame, scaling, session timer, tweaks. */
const { useState: uS, useEffect: uE, useRef: uR, useCallback: uC } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "dark",
  "accent": "plasma",
  "font": "space",
  "density": "regular",
  "radius": 18,
  "orientation": "landscape",
  "lanes": 20,
  "perRow": 5,
  "lang": "en",
  "currency": "€",
  "demoFails": false
}/*EDITMODE-END*/;

const FRAMES = {
  landscape: { w: 1280, h: 800 },
  portrait: { w: 1024, h: 1280 },
};

function useScale(orientation, deps) {
  const [scale, setScale] = uS(1);
  uE(() => {
    const f = FRAMES[orientation];
    const recompute = () => {
      const pad = 48;
      const s = Math.min((window.innerWidth - pad) / (f.w + 56), (window.innerHeight - pad) / (f.h + 56));
      setScale(Math.max(0.2, Math.min(s, 1.1)));
    };
    recompute();
    window.addEventListener('resize', recompute);
    return () => window.removeEventListener('resize', recompute);
  }, [orientation, deps]);
  return scale;
}

const ACCENTS = [
  { id: 'plasma', hex: '#9b6bff' }, { id: 'aqua', hex: '#37c4d8' }, { id: 'voltage', hex: '#c6e84a' },
  { id: 'ember', hex: '#e08a3a' }, { id: 'magenta', hex: '#e052a3' },
];
function AccentPicker({ value, onChange }) {
  return (
    <TweakRow label="Accent">
      <div style={{ display: 'flex', gap: 8 }}>
        {ACCENTS.map((a) => (
          <button key={a.id} onClick={() => onChange(a.id)} title={a.id}
            style={{ width: 30, height: 30, borderRadius: 8, background: a.hex, cursor: 'pointer',
              border: value === a.id ? '2px solid #fff' : '2px solid transparent',
              boxShadow: value === a.id ? '0 0 0 2px #000, 0 0 10px ' + a.hex : 'none', outline: 'none' }} />
        ))}
      </div>
    </TweakRow>
  );
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const tr = makeT(t.lang);
  const ctx = { t: tr, lang: t.lang, cur: t.currency, orientation: t.orientation };

  const [view, setView] = uS('standby'); // standby, catalog, agecheck, payment, pickup
  const [selected, setSelected] = uS(null);
  const [dialog, setDialog] = uS(null); // lang, help
  const [admin, setAdmin] = uS(false);
  const [sessionLeft, setSessionLeft] = uS(120);
  const logoTaps = uR([]);

  const scale = useScale(t.orientation, [dialog, admin]);
  const f = FRAMES[t.orientation];
  const cols = t.perRow || colsFor(t.lanes, t.orientation);
  const lanes = buildLanes(t.lanes, cols);

  // ---- session inactivity timer ----
  const resetSession = uC(() => setSessionLeft(120), []);
  uE(() => {
    if (view === 'standby' || admin) return;
    if (sessionLeft <= 0) { backToStandby(); return; }
    const id = setTimeout(() => setSessionLeft((s) => s - 1), 1000);
    return () => clearTimeout(id);
  }, [view, sessionLeft, admin]);

  const backToStandby = () => { setView('standby'); setSelected(null); setDialog(null); };

  // triple-tap logo → admin
  const onLogo = () => {
    const now = Date.now();
    logoTaps.current = [...logoTaps.current.filter((x) => now - x < 1200), now];
    if (logoTaps.current.length >= 3) { logoTaps.current = []; setAdmin(true); }
  };

  const pickLang = (code) => { setTweak('lang', code); setDialog(null); };

  // ---- flow handlers ----
  const wake = () => { resetSession(); setView('catalog'); };
  const selectProduct = (p) => { setSelected(p); resetSession(); };
  const checkout = () => { resetSession(); setView('agecheck'); };
  const ageDone = () => { resetSession(); setView('payment'); };
  const paySuccess = () => { resetSession(); setView('pickup'); };

  let screen;
  if (view === 'standby') screen = <StandbyScreen ctx={ctx} onWake={wake} onLang={pickLang} />;
  else if (view === 'catalog') screen = <CatalogScreen ctx={ctx} lanes={lanes} cols={cols} selected={selected} onSelect={selectProduct} onClear={() => setSelected(null)} onCheckout={checkout} onLogo={onLogo} onHelp={() => setDialog('help')} onLang={() => setDialog('lang')} sessionLeft={sessionLeft} />;
  else if (view === 'agecheck') screen = <AgeCheckScreen ctx={ctx} forceFail={t.demoFails} onComplete={ageDone} onCancel={() => setView('catalog')} />;
  else if (view === 'payment') screen = <PaymentScreen ctx={ctx} item={selected} forceFail={t.demoFails} onSuccess={paySuccess} onCancel={() => setView('catalog')} />;
  else if (view === 'pickup') screen = <PickupScreen ctx={ctx} item={selected} lanes={lanes} cols={cols} forceFail={t.demoFails} onDone={backToStandby} />;

  return (
    <div className="stagewrap">
      <div className="bezel" style={{ transform: `scale(${scale})` }}>
        <div className="cam-dot" />
        <div className="kiosk" data-theme={t.theme} data-accent={t.accent} data-font={t.font}
          data-density={t.density} data-orientation={t.orientation}
          style={{ width: f.w, height: f.h, '--radius': t.radius + 'px' }}
          onPointerDown={view !== 'standby' && !admin ? resetSession : undefined}>
          {screen}
          {dialog === 'lang' && <LangDialog ctx={ctx} onPick={pickLang} onClose={() => setDialog(null)} />}
          {dialog === 'help' && <HelpDialog ctx={ctx} onClose={() => setDialog(null)} />}
          {admin && <AdminScreen ctx={ctx} lanes={lanes} onExit={() => setAdmin(false)} />}
        </div>
      </div>

      <TweaksPanel>
        <TweakSection label="Brand · Theme" />
        <AccentPicker value={t.accent} onChange={(v) => setTweak('accent', v)} />
        <TweakRadio label="Mode" value={t.theme} options={['dark', 'light']} onChange={(v) => setTweak('theme', v)} />
        <TweakSection label="Type · Layout" />
        <TweakSelect label="Display font" value={t.font}
          options={[{ value: 'space', label: 'Space Grotesk' }, { value: 'sora', label: 'Sora' }, { value: 'bricolage', label: 'Bricolage' }, { value: 'archivo', label: 'Archivo' }]}
          onChange={(v) => setTweak('font', v)} />
        <TweakRadio label="Density" value={t.density} options={['compact', 'regular', 'comfy']} onChange={(v) => setTweak('density', v)} />
        <TweakSlider label="Corner radius" value={t.radius} min={0} max={30} step={2} unit="px" onChange={(v) => setTweak('radius', v)} />
        <TweakSection label="Kiosk" />
        <TweakRadio label="Lanes (货道)" value={String(t.lanes)} options={['9', '12', '20']} onChange={(v) => setTweak('lanes', parseInt(v, 10))} />
        <TweakRadio label="Per row (每行)" value={String(t.perRow)} options={['3', '4', '5']} onChange={(v) => setTweak('perRow', parseInt(v, 10))} />
        <TweakRadio label="Orientation" value={t.orientation} options={['landscape', 'portrait']} onChange={(v) => setTweak('orientation', v)} />
        <TweakSelect label="Language" value={t.lang}
          options={LANGS.map((l) => ({ value: l.code, label: l.flag + ' ' + l.label }))}
          onChange={(v) => setTweak('lang', v)} />
        <TweakRadio label="Currency" value={t.currency} options={['€', '£', '$']} onChange={(v) => setTweak('currency', v)} />
        <TweakToggle label="Demo failure states" value={t.demoFails} onChange={(v) => setTweak('demoFails', v)} />
        <TweakButton label="Jump to standby" onClick={backToStandby} />
      </TweaksPanel>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
