// app.jsx — router, global state, mount (load LAST)
const { useState: useStateApp, useRef: useRefApp, useEffect: useEffectApp } = React;

// Self-report quest player (hydration etc.)
function SelfReport({ quest, onDone, onClose }) {
  return (
    <Screen bg={T.surface}>
      <div style={{ paddingTop: 8 }}><TopBar title={quest.title} right={
        <button onClick={onClose} style={{ width: 42, height: 42, borderRadius: 999, background: T.surface2, border: 'none', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="close" size={20} color={T.ink2} sw={2.2}/></button>
      }/></div>
      <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', paddingTop: 50 }}>
        <div style={{ width: 96, height: 96, borderRadius: 28, background: T.calmSoft, display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 24 }}>
          <Icon name="drop" size={46} color={T.calm}/>
        </div>
        <h1 style={{ fontSize: 25, fontWeight: 800, color: T.ink, letterSpacing: -0.5, margin: '0 0 8px' }}>{quest.title}</h1>
        <p style={{ fontSize: 15.5, color: T.ink2, margin: 0 }}>완료했나요? 정직하게 체크하면 돼요.</p>
      </div>
      <FloatCTA>
        <Btn variant="calm" onClick={onDone}>마셨어요</Btn>
        <Btn variant="ghost" size="md" style={{ marginTop: 6 }} onClick={onClose}>나중에</Btn>
      </FloatCTA>
    </Screen>
  );
}

function App() {
  const [phase, setPhase] = useStateApp('ftue');
  const initTheme = (() => { try { return localStorage.getItem('fb_theme') || 'light'; } catch (e) { return 'light'; } })();
  const [theme, setTheme] = useStateApp(initTheme);
  const [data, setData] = useStateApp({ level: 2, xp: 120, streak: 3, energy: 3, maxEnergy: 5, pro: false, nextSec: 1140, homeVariant: 'default', completedToday: false });
  const [backend, setBackend] = useStateApp(null);
  const [route, setRoute] = useStateApp({ name: 'home', params: {} });
  const hist = useRefApp([]);

  // apply theme synchronously on every render so it survives navigation
  window.applyTheme(theme);
  const toggleTheme = () => setTheme(t => t === 'dark' ? 'light' : 'dark');

  useEffectApp(() => {
    let mounted = true;
    const api = window.FitbodyBackend;
    if (!api) return undefined;
    api.bootstrap().then(snapshot => {
      if (!mounted) return;
      setBackend(snapshot);
      setData(d => api.dataFromSnapshot ? api.dataFromSnapshot(snapshot, d) : d);
    }).catch(() => {
      if (!mounted) return;
      const snapshot = api.snapshot();
      setBackend(snapshot);
      setData(d => api.dataFromSnapshot ? api.dataFromSnapshot(snapshot, d) : d);
    });
    return () => { mounted = false; };
  }, []);

  // energy recharge timer
  useEffectApp(() => {
    const iv = setInterval(() => {
      setData(d => {
        if (d.pro || d.energy >= d.maxEnergy) return d;
        if (d.nextSec <= 1) return { ...d, energy: Math.min(d.maxEnergy, d.energy + 1), nextSec: 1500 };
        return { ...d, nextSec: d.nextSec - 1 };
      });
    }, 1000);
    return () => clearInterval(iv);
  }, []);

  const go = (name, params = {}) => { hist.current.push(route); setRoute({ name, params }); };
  const back = () => { const h = hist.current; setRoute(h.length ? h.pop() : { name: 'home', params: {} }); };
  const navTab = (tab) => { hist.current = []; setPhase('app'); setRoute({ name: tab, params: {} }); };
  window.__nav = navTab;

  // spend 1 energy for an extra quest; free===true bypasses (daily core quest)
  const startQuest = (q, free) => {
    if (free || data.pro || data.energy > 0) {
      if (!free && !data.pro) setData(d => ({ ...d, energy: Math.max(0, d.energy - 1) }));
      if (window.FitbodyBackend) window.FitbodyBackend.beginQuest(q).catch(() => {});
      go('player', { quest: q });
    } else {
      go('energy', { quest: q });
    }
  };

  const applyCompletion = (questOrXp) => {
    const quest = typeof questOrXp === 'object' ? questOrXp : null;
    const xp = quest ? (quest.xp || 10) : (questOrXp || 0);
    if (quest && window.FitbodyBackend) {
      window.FitbodyBackend.completeQuest(quest).catch(() => {});
    }
    setData(d => ({
      ...d,
      xp: d.xp + xp,
      energy: d.pro ? d.energy : Math.min(d.maxEnergy, d.energy + 1), // completing tops up 1
      streak: d.completedToday ? d.streak : d.streak + 1,
      completedToday: true,
      homeVariant: 'completed',
    }));
  };

  if (phase === 'ftue') {
    return <FTUE onFinish={() => { setData(d => ({ ...d, completedToday: false, homeVariant: 'default' })); setPhase('app'); navTab('home'); }}/>;
  }

  const { name, params } = route;

  if (name === 'player') {
    const q = params.quest;
    if (q.selfReport) return <SelfReport quest={q} onClose={back} onDone={() => go('completion', { quest: q })}/>;
    return <QuestPlayer {...q} onDone={() => go('completion', { quest: q })} onClose={back}/>;
  }

  if (name === 'completion') {
    const q = params.quest || {};
    const xp = q.xp || 10;
    return <CompletionView xp={xp} streakDay={data.completedToday ? data.streak : data.streak + 1} tone={q.tone || T.coral} pro={data.pro}
      avaLine={q.tone === T.calm ? '피곤한 날에는 밀어붙이지 않는 것도 훈련이에요. 회복 완료.' : '좋아요. 오늘 건강 행동이 기록됐어요.'}
      primary={{ label: '홈으로 가기', onClick: () => { applyCompletion(q); navTab('home'); } }}
      secondary={{ label: 'Progress 보기', onClick: () => { applyCompletion(q); navTab('progress'); } }}
    />;
  }

  if (name === 'energy') return <EnergyScreen data={data} setData={setData} back={back} go={go} resume={params.quest}/>;
  if (name === 'ad') return <AdScreen onDone={() => { setData(d => ({ ...d, energy: Math.min(d.maxEnergy, d.energy + 1) })); back(); }}/>;
  if (name === 'subscribe') return <SubscribeScreen data={data} onSubscribe={() => {
    if (window.FitbodyBackend) window.FitbodyBackend.subscribe('pro').then(url => { if (url) window.location.href = url; }).catch(() => {});
    setData(d => ({ ...d, pro: true }));
    back();
  }} back={back}/>;
  if (name === 'academy') return <Academy exit={() => navTab('home')} startQuest={startQuest} data={data} spendEnergy={() => setData(d => ({ ...d, energy: d.pro ? d.energy : Math.max(0, d.energy - 1) }))} onReward={(xp) => setData(d => ({ ...d, xp: d.xp + (xp || 0) }))}/>;
  if (name === 'academyAt') return <Academy initial={params.at} exit={() => navTab('home')} startQuest={startQuest} data={data} spendEnergy={() => setData(d => ({ ...d, energy: d.pro ? d.energy : Math.max(0, d.energy - 1) }))} onReward={(xp) => setData(d => ({ ...d, xp: d.xp + (xp || 0) }))}/>;
  if (name === 'bodycheck') return <BodyCheck initial={params.at} exit={back} startQuest={(q) => startQuest(q)}/>;
  if (name === 'flow') return <Flow flow={params.flow} go={go} back={back} startQuest={startQuest}/>;
  if (name === 'quest') return <QuestTab go={go} data={data} startQuest={startQuest}/>;
  if (name === 'league') return <League go={go} data={data} startQuest={startQuest}/>;
  if (name === 'invite') return <InviteFriends go={go} back={back}/>;
  if (name === 'progress') return <Progress data={data} go={go}/>;
  if (name === 'profile') return <ProfileScreen data={data} go={go}/>;
  if (name === 'settings') return <Settings go={go} setData={setData} theme={theme} toggleTheme={toggleTheme}/>;
  if (name === 'notifications') return <Notifications go={go} backend={backend}/>;
  return <Home data={data} go={go} startQuest={startQuest}/>;
}

// scale phone to fit viewport
function fitPhone() {
  const stage = document.getElementById('stage');
  if (!stage) return;
  const pad = 32;
  const s = Math.min((window.innerWidth - pad) / PHONE_W, (window.innerHeight - pad) / PHONE_H);
  stage.style.transform = `scale(${Math.min(s, 1)})`;
}
window.addEventListener('resize', fitPhone);

ReactDOM.createRoot(document.getElementById('phone-root')).render(<App/>);
setTimeout(fitPhone, 50);
