// App shell — manages scene stack, camera-dolly transitions, audio, tweaks,
// and the cursor lantern. Loads after content.jsx, audio.jsx, lantern.jsx,
// scenes.jsx, and tweaks-panel.jsx.

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "redIntensity": "thin",
  "hubMetaphor": "corridor",
  "typePair": "mono",
  "transitionSpeed": 550,
  "fog": 100,
  "breath": 100,
  "audio": true
}/*EDITMODE-END*/;

function CustomCursor() {
  const [pos, setPos] = React.useState({ x: -100, y: -100 });

  React.useEffect(() => {
    let raf;
    const target = { x: -100, y: -100 };
    const onMove = (e) => { target.x = e.clientX; target.y = e.clientY; };
    const tick = () => {
      setPos((p) => ({ x: p.x + (target.x - p.x) * 0.22, y: p.y + (target.y - p.y) * 0.22 }));
      raf = requestAnimationFrame(tick);
    };
    window.addEventListener('mousemove', onMove);
    tick();
    return () => { window.removeEventListener('mousemove', onMove); cancelAnimationFrame(raf); };
  }, []);

  return <div className="cursor-wisp" style={{ left: pos.x, top: pos.y }} />;
}

function AudioToggle({ enabled, onToggle }) {
  return (
    <button className="audio-toggle" data-on={enabled ? '1' : '0'}
            onClick={onToggle}>
      <span className="dot" />
      <span>{enabled ? 'audio · on' : 'audio · off'}</span>
    </button>
  );
}

function useIsMobile(breakpoint = 820) {
  const get = () => typeof window !== 'undefined' && window.innerWidth < breakpoint;
  const [isMobile, setIsMobile] = React.useState(get);
  React.useEffect(() => {
    const onResize = () => setIsMobile(get());
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, []);
  return isMobile;
}

function App() {
  const isMobile = useIsMobile();
  return isMobile ? <MobileSite /> : <DesktopApp />;
}

function DesktopApp() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [scene, setScene] = React.useState('cover');   // cover | hub | chapter | poem
  const [poemId, setPoemId] = React.useState(null);
  const [dayId, setDayId] = React.useState('mon');
  const [transitioning, setTransitioning] = React.useState(false);
  const audio = useAudio(t.audio);

  // Wire transition speed to CSS var.
  React.useEffect(() => {
    document.documentElement.style.setProperty('--t-slow', `${t.transitionSpeed}ms cubic-bezier(.22,.61,.36,1)`);
    document.documentElement.style.setProperty('--t-med',  `${Math.round(t.transitionSpeed * 0.65)}ms cubic-bezier(.22,.61,.36,1)`);
  }, [t.transitionSpeed]);

  // Red intensity affects --red color directly.
  React.useEffect(() => {
    const map = {
      surgical: { c: 0.12, op: 0.4 },
      thin:     { c: 0.18, op: 0.55 },
      bloodier: { c: 0.24, op: 0.75 },
    };
    const r = map[t.redIntensity] || map.thin;
    document.documentElement.style.setProperty('--red', `oklch(0.55 ${r.c} 25)`);
    document.documentElement.style.setProperty('--red-dim', `oklch(0.55 ${r.c} 25 / ${r.op})`);
    document.documentElement.style.setProperty('--red-faint', `oklch(0.55 ${r.c} 25 / ${r.op * 0.5})`);
  }, [t.redIntensity]);

  // Type pairing
  React.useEffect(() => {
    const families = {
      mono:        "'JetBrains Mono', ui-monospace, Menlo, Consolas, monospace",
      serif:       "'EB Garamond', Georgia, serif",
      mixed:       "'JetBrains Mono', ui-monospace, monospace",
    };
    document.documentElement.style.setProperty('--font', families[t.typePair] || families.mono);
  }, [t.typePair]);

  const navigate = (target, opts = {}) => {
    if (transitioning) return;
    setTransitioning(true);
    audio.tick('thud');
    setTimeout(() => {
      if (target === 'poem') setPoemId(opts.poemId);
      if (target === 'chapter' && opts.dayId) setDayId(opts.dayId);
      setScene(target);
      // Wind whoosh fires *with* the visual scene swap, not on click.
      if (audio.sting) audio.sting();
      setTransitioning(false);
    }, t.transitionSpeed * 0.3);
  };

  return (
    <>
      <CustomCursor />
      <LanternProvider intensity={t.breath / 100}>
        <AudioToggle enabled={t.audio} onToggle={() => setTweak('audio', !t.audio)} />

        <div className="scene-stack">
          <div className={`scene ${scene === 'cover' ? 'scene--active' : 'scene--exit'}`}>
            {scene === 'cover' && (
              <Cover onOpen={() => navigate('hub')} tweaks={t} audio={audio} />
            )}
          </div>
          <div className={`scene ${scene === 'hub' ? 'scene--active' : (scene === 'cover' ? 'scene--enter' : 'scene--exit')}`}>
            {scene === 'hub' && (
              <Hub onNavigate={(id) => navigate('chapter', { dayId: id })}
                   tweaks={t} audio={audio} />
            )}
          </div>
          <div className={`scene ${scene === 'chapter' ? 'scene--active' : 'scene--enter'}`}>
            {scene === 'chapter' && (
              <ChapterReader
                dayId={dayId}
                onBack={() => navigate('hub')}
                onPoem={(id) => navigate('poem', { poemId: id })}
                audio={audio}
              />
            )}
          </div>
          <div className={`scene ${scene === 'poem' ? 'scene--active' : 'scene--enter'}`}>
            {scene === 'poem' && (
              <PoemScene poemId={poemId} onBack={() => navigate('chapter')} audio={audio} />
            )}
          </div>
        </div>

        <TweaksPanel title="Tweaks">
          <TweakSection label="Atmosphere" />
          <TweakRadio label="Red intensity" value={t.redIntensity}
            options={[{value:'surgical',label:'surgical'},{value:'thin',label:'thin'},{value:'bloodier',label:'blood'}]}
            onChange={(v) => setTweak('redIntensity', v)} />
          <TweakSlider label="Fog" value={t.fog} min={0} max={150} unit="%"
            onChange={(v) => setTweak('fog', v)} />
          <TweakSlider label="Breath / flicker" value={t.breath} min={20} max={200} unit="%"
            onChange={(v) => setTweak('breath', v)} />

          <TweakSection label="Type" />
          <TweakRadio label="Pairing" value={t.typePair}
            options={[{value:'mono',label:'mono'},{value:'serif',label:'serif'},{value:'mixed',label:'mix'}]}
            onChange={(v) => setTweak('typePair', v)} />

          <TweakSection label="Hub" />
          <TweakRadio label="Metaphor" value={t.hubMetaphor}
            options={[{value:'corridor',label:'corridor'},{value:'desk',label:'desk'},{value:'book',label:'book'}]}
            onChange={(v) => setTweak('hubMetaphor', v)} />

          <TweakSection label="Motion" />
          <TweakSlider label="Transition" value={t.transitionSpeed} min={400} max={2200} step={50} unit="ms"
            onChange={(v) => setTweak('transitionSpeed', v)} />

          <TweakSection label="Audio" />
          <TweakToggle label="Hum + ticks" value={t.audio}
            onChange={(v) => setTweak('audio', v)} />

          <TweakSection label="Jump to" />
          <div style={{display:'flex',flexDirection:'column',gap:6}}>
            <TweakButton secondary label="Cover"        onClick={() => setScene('cover')} />
            <TweakButton secondary label="Hub"          onClick={() => setScene('hub')} />
            <TweakButton secondary label="Monday"       onClick={() => setScene('chapter')} />
            <TweakButton secondary label="Poem · Identity" onClick={() => { setPoemId('identity'); setScene('poem'); }} />
            <TweakButton secondary label="Poem · Tick Tock" onClick={() => { setPoemId('tick'); setScene('poem'); }} />
          </div>
        </TweaksPanel>
      </LanternProvider>
    </>
  );
}

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