// app.jsx — root app, router, URL state controller, dev panel
// URL params: ?screen=P01&state=loading&theme=dark&offline=1&widget=mascot
// Screen list:
//   P01 (login), P02 (home), P03 (allseeds), P04 (collection),
//   P05 (seed), P06, P06a, P06b, P06c, P07 (search), P08, P09,
//   P12 (me), P13 (settings), P14 (help), terms, privacy,
//   P-ad-pre, P-ad-consent, P-ad-reward

// ── URL state ─────────────────────────────────────────────
function useQuery() {
  const get = () => {
    const u = new URLSearchParams(window.location.search);
    return {
      screen:  u.get('screen')  || 'P01',
      state:   u.get('state')   || 'default',
      from:    u.get('from'),
      theme:   u.get('theme')   || 'light',
      offline: u.get('offline') === '1',
      seedId:  u.get('seedId'),
      pouchId: u.get('pouchId'),
      cat:     u.get('cat'),
      catLabel: u.get('catLabel'),
      fav:     u.get('fav') === '1',
      hideDev: u.get('hideDev') === '1',
      hideStatus: u.get('hideStatus') === '1',
      hideTab: u.get('hideTab') === '1',
      noFrame: u.get('noFrame') === '1',
    };
  };
  const [q, setQ] = React.useState(get());
  React.useEffect(() => {
    const on = () => setQ(get());
    window.addEventListener('popstate', on);
    window.addEventListener('cp-url', on);
    return () => {
      window.removeEventListener('popstate', on);
      window.removeEventListener('cp-url', on);
    };
  }, []);
  const update = (patch) => {
    const u = new URLSearchParams(window.location.search);
    Object.entries(patch).forEach(([k, v]) => {
      if (v == null || v === false || v === '') u.delete(k);
      else u.set(k, v === true ? '1' : v);
    });
    const newUrl = window.location.pathname + (u.toString() ? '?' + u.toString() : '');
    window.history.replaceState(null, '', newUrl);
    window.dispatchEvent(new Event('cp-url'));
  };
  return [q, update];
}

// ── Apply theme to <html> synchronously (so first render is correct) ──
function applyTheme(theme) {
  const root = document.documentElement;
  if (theme === 'dark') root.classList.add('cp-dark');
  else root.classList.remove('cp-dark');
}

// ── Screen registry ───────────────────────────────────────
function ScreenSwitch({ q, set, boost, applyBoost }) {
  const navigate = (target, params = {}) => {
    if (target === 'back') {
      // simple back: most screens go back to home / settings parent
      const cur = q.screen;
      let to = 'P02';
      if (cur === 'P14' || cur === 'P13a' || cur === 'P13b') to = 'P13';
      else if (cur === 'P05' && (q.from === 'P10' || q.from === 'P10m')) {
        // Came from P10 — return to P10, preserving the original (default
        // vs multi) state. `from=P10m` means user was in multi list.
        set({ screen: 'P10', state: q.from === 'P10m' ? 'multi' : null,
              seedId: null, from: null });
        return;
      }
      else if (cur === 'P04' && q.from === 'P05' && q.seedId) {
        // Came from a seed's pouch chip — return to the seed detail,
        // not all the way home.
        set({ screen: 'P05', state: null, pouchId: null, from: null });
        return;
      }
      else if (cur === 'P03' && q.from === 'P12') {
        // Came from the 나 탭 곳간 — return there, clearing the fav filter param.
        set({ screen: 'P12', state: null, fav: null, from: null });
        return;
      }
      else if (cur === 'P03' && q.from === 'P13b') {
        // Came from a category in 카테고리 관리 — return to P13b.
        set({ screen: 'P13b', state: null, cat: null, catLabel: null, from: null });
        return;
      }
      else if (cur === 'P13' || cur === 'P05' || cur === 'P06') to = 'P02';
      else if (cur && cur.startsWith('P06')) to = 'P06';
      else if (cur === 'P03' || cur === 'P04' || cur === 'P04a' || cur === 'P07' || cur === 'P08' || cur === 'P09' || cur === 'P10') to = 'P02';
      else if (cur === 'P12') to = 'P02';
      else if (cur === 'terms' || cur === 'privacy') to = q.from || 'P01';
      set({ screen: to, state: null, seedId: null, pouchId: null, fav: null, cat: null, catLabel: null, from: null });
      return;
    }
    set({ screen: target, state: null, ...params });
  };
  const goTab = (tab) => {
    set({ screen: tab === 'home' ? 'P02' : 'P12', state: null });
  };

  const base = window.MOCK_USER;
  // Today's cap expands when the user watches an ad. todayPouch (filled) is
  // unchanged — caps stretch to make room. Boost count decrements.
  const user = {
    ...base,
    todayCap:   (base.todayCap   ?? 10) + boost.extraSlots,
    todayBoost: Math.max(0, (base.todayBoost ?? 0) - boost.used),
  };
  const state = q.state || 'default';
  const offline = q.offline ? 'offline' : state;

  switch (q.screen) {
    case 'P01': return <ScreenLogin
      state={q.offline ? 'offline' : state}
      busyProvider={state === 'loading' ? 'apple' : null}
      onSignIn={() => set({ screen: 'P02', state: null })}
      onShowTerms={() => set({ screen: 'terms', from: 'P01' })}
      onShowPrivacy={() => set({ screen: 'privacy', from: 'P01' })}/>;
    case 'terms':   return <ScreenLegal kind="terms"   onClose={() => set({ screen: q.from || 'P01', from: null })}/>;
    case 'privacy': return <ScreenLegal kind="privacy" onClose={() => set({ screen: q.from || 'P01', from: null })}/>;

    case 'P02': return <ScreenHome state={offline} onNavigate={navigate}
      user={state === 'empty' ? { ...user, totalSeeds: 0, recentSeedIds: [] } : user}/>;
    case 'P03': return <ScreenAllSeeds key={`${state}-${q.offline ? 1 : 0}-${q.cat || ''}`} state={offline} onNavigate={navigate} initialFav={q.fav} initialFilter={q.cat ? { cat: q.cat } : undefined}/>;
    case 'P04': return <ScreenCollection state={offline} onNavigate={navigate} pouchId={q.pouchId}/>;
    case 'P04a': return <ScreenAllPouches state={offline} onNavigate={navigate}/>;
    case 'P05': return <ScreenSeed key={`${state}-${q.seedId || 's01'}`} state={offline} onNavigate={navigate} seedId={q.seedId} from={q.from}/>;

    case 'P06':  return <ScreenInput  state={offline} onNavigate={navigate} user={user}/>;
    case 'P06a': return <ScreenInputTyping     state={offline} onNavigate={navigate}/>;
    case 'P06b': return <ScreenInputVoice      key={state}      state={offline} onNavigate={navigate}/>;
    case 'P06c': return <ScreenInputScreenshot key={state}      state={offline} onNavigate={navigate}/>;

    case 'P07': return <ScreenSearch key={state} state={offline} onNavigate={navigate} user={user}/>;
    case 'P08': return <ScreenNewCollection onNavigate={navigate}/>;
    case 'P09': return <ScreenProcessing state={offline} onNavigate={navigate}/>;
    case 'P10': return <ScreenProcessed key={state} state={offline} onNavigate={navigate}/>;

    case 'P12': return <ScreenMe key={state} state={offline} onNavigate={navigate} user={user}/>;
    case 'P13': return <ScreenSettings
      state={offline} onNavigate={navigate}
      onSetTheme={(v) => set({ theme: v === 'system' ? 'light' : v })}
      theme={q.theme === 'dark' ? 'dark' : (q.theme === 'light' ? 'light' : 'system')}
      onLogout={() => set({ screen: 'P01', state: null })}
      onDeleteAccount={() => set({ screen: 'P01', state: null })}/>;
    case 'P14': return <ScreenHelp onNavigate={navigate}/>;
    case 'P13b': return <ScreenCategories state={q.offline ? 'offline' : (state === 'default' ? null : state)} onNavigate={navigate}/>;

    case 'P-ad-pre':
      return <ScreenAdPre
        onContinue={() => set({ screen: 'P-ad-consent' })}
        onClose={() => set({ screen: 'P12' })}/>;
    case 'P-ad-consent':
      return <ScreenAdConsent
        onAccept={() => set({ screen: 'P-ad-reward', state: 'allowed' })}
        onDeny={() => set({ screen: 'P-ad-reward', state: 'denied' })}/>;
    case 'P-ad-reward': {
      const amount = state === 'denied' ? 1 : 3;
      return <ScreenAdReward
        amount={amount}
        allowed={state !== 'denied'}
        user={user}
        newCap={user.todayCap + amount}
        onDone={() => { applyBoost(amount); set({ screen: 'P12', state: null }); }}/>;
    }

    default: return <ScreenLogin/>;
  }
}

// ── Tab bar visibility per screen ─────────────────────────
function tabForScreen(s) {
  if (s === 'P02' || s === 'P03' || s === 'P04' || s === 'P04a' || s === 'P07' || s === 'P08') return 'home';
  if (s === 'P12' || s === 'P13' || s === 'P14' || s === 'P13a' || s === 'P13b') return 'me';
  return null;
}
function hasTabBar(s) {
  // tab bar only on main tab roots
  return s === 'P02' || s === 'P12';
}

// ── Dev controls panel (left side, collapsible) ───────────
function DevPanel({ q, set }) {
  const [open, setOpen] = React.useState(true);
  if (q.hideDev) return null;

  const SCREENS = [
    { id: 'P01', label: 'P01 로그인',          states: ['default','loading','failed','offline'] },
    { id: 'terms',   label: 'P01-terms 약관',    states: [] },
    { id: 'privacy', label: 'P01-privacy 개인정보', states: [] },
    { id: 'P02', label: 'P02 홈',              states: ['default','empty','noPouches','full','offline'] },
    { id: 'P03', label: 'P03 내 씨앗',          states: ['default','playing','paused','empty','filterSheet','offline'] },
    { id: 'P04', label: 'P04 주머니 상세',      states: ['default','playing','empty','nameEdit'] },
    { id: 'P04a',label: 'P04a 내 주머니',          states: ['default','empty','offline'] },
    { id: 'P05', label: 'P05 씨앗 상세',        states: ['default','playingPhrase','playingDialogue','unfiled'] },
    { id: 'P06', label: 'P06 입력 선택',        states: ['default','full','offline'] },
    { id: 'P06a',label: 'P06a 타이핑',          states: ['default','foreign','offline'] },
    { id: 'P06b',label: 'P06b 음성',            states: ['default','recording','transcribed','transcribed-foreign','denied'] },
    { id: 'P06c',label: 'P06c 스크린샷',        states: ['source','picker','camera','clipboard','preview','detect','confirm','confirm-foreign','confirm-mixed'] },
    { id: 'P07', label: 'P07 검색',             states: ['default','results','empty'] },
    { id: 'P08', label: 'P08 새 주머니',        states: [] },
    { id: 'P09', label: 'P09 만드는 중',        states: ['default','multi','error'] },
    { id: 'P10', label: 'P10 씨앗 만들었어요',     states: ['default','multi'] },
    { id: 'P12', label: 'P12 나',               states: ['default','noFav','bubble','denied','offline'] },
    { id: 'P13', label: 'P13 설정',             states: ['default','offline'] },
    { id: 'P13b',label: 'P13b 카테고리 관리',    states: ['empty','searchEmpty','loading','offline','error'] },
    { id: 'P14', label: 'P14 도움말',           states: [] },
    { id: 'P-ad-pre',     label: '광고 사전 안내', states: [] },
    { id: 'P-ad-consent', label: '광고 추적 동의', states: [] },
    { id: 'P-ad-reward',  label: '광고 보상',     states: ['allowed','denied'] },
  ];

  const cur = SCREENS.find(s => s.id === q.screen);

  return (
    <div data-noncommentable style={{
      position: 'fixed', top: 16, left: 16,
      zIndex: 200,
      background: '#FFF',
      borderRadius: 14, border: '1px solid #00000014',
      boxShadow: '0 10px 32px rgba(0,0,0,0.12)',
      width: open ? 260 : 44,
      transition: 'width .2s ease',
      overflow: 'hidden',
      fontFamily: 'Pretendard, -apple-system, system-ui, sans-serif',
    }}>
      <button onClick={() => setOpen(o => !o)} style={{
        width: '100%', height: 44,
        background: '#1F1812', color: '#FBF7F0',
        border: 'none', display: 'flex', alignItems: 'center', gap: 8,
        padding: '0 14px', cursor: 'pointer',
        fontSize: 13, fontWeight: 700, letterSpacing: '-0.01em',
        fontFamily: 'inherit',
      }}>
        <span style={{ fontSize: 16 }}>🐹</span>
        {open && <span style={{ flex: 1, textAlign: 'left' }}>CheekPouch MVP</span>}
        {open && <span style={{ fontSize: 11, opacity: 0.6 }}>{q.screen}</span>}
      </button>
      {open && (
        <div style={{ padding: 12 }}>
          <Field label="화면 (screen)">
            <select value={q.screen} onChange={e => set({ screen: e.target.value, state: null })}
                    style={selectStyle}>
              {SCREENS.map(s => <option key={s.id} value={s.id}>{s.label}</option>)}
            </select>
          </Field>
          {cur?.states?.length > 0 && (
            <Field label="상태 (state)">
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>
                {['default', ...cur.states.filter(s => s !== 'default')].map(s => (
                  <button key={s} onClick={() => set({ state: s === 'default' ? null : s })}
                          style={{
                    padding: '5px 9px', borderRadius: 10,
                    background: (q.state || 'default') === s ? '#1F1812' : '#FBF7F0',
                    color: (q.state || 'default') === s ? '#FFF' : '#1F1812',
                    border: '1px solid rgba(0,0,0,0.08)',
                    fontSize: 11, fontWeight: 600,
                    cursor: 'pointer', fontFamily: 'inherit',
                  }}>{s}</button>
                ))}
              </div>
            </Field>
          )}
          <Field label="테마">
            <div style={{ display: 'flex', gap: 4 }}>
              {[['light', '라이트', '☀'], ['dark', '다크', '☾']].map(([v, l, ic]) => (
                <button key={v} onClick={() => set({ theme: v })} style={{
                  flex: 1, padding: '7px', borderRadius: 10,
                  background: q.theme === v ? '#1F1812' : '#FBF7F0',
                  color: q.theme === v ? '#FFF' : '#1F1812',
                  border: '1px solid rgba(0,0,0,0.08)',
                  fontSize: 11.5, fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit',
                }}>{ic} {l}</button>
              ))}
            </div>
          </Field>
          <Field label="오프라인">
            <button onClick={() => set({ offline: !q.offline })} style={{
              width: '100%', padding: '7px',
              borderRadius: 10,
              background: q.offline ? '#8B6F47' : '#FBF7F0',
              color: q.offline ? '#FFF' : '#1F1812',
              border: '1px solid rgba(0,0,0,0.08)',
              fontSize: 11.5, fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit',
            }}>{q.offline ? '✈ 오프라인 ON' : '온라인'}</button>
          </Field>

          <div style={{ paddingTop: 8, borderTop: '0.5px solid #00000014', marginTop: 10,
                        fontSize: 10.5, color: '#6B5D4A', lineHeight: 1.5 }}>
            URL: <code style={{ fontSize: 10, color: '#1F1812' }}>?screen={q.screen}&state={q.state || 'default'}</code>
          </div>

          <div style={{ marginTop: 10, display: 'flex', gap: 4 }}>
            <a href="../index.html" style={linkStyle}>← 허브</a>
            <a href="screens.html" style={linkStyle}>화면×상태</a>
            <a href="widgets.html" style={linkStyle}>위젯</a>
          </div>
        </div>
      )}
    </div>
  );
}

const selectStyle = {
  width: '100%', height: 32,
  background: '#FBF7F0', border: '1px solid rgba(0,0,0,0.1)',
  borderRadius: 10, padding: '0 8px',
  fontSize: 12, fontFamily: 'inherit', color: '#1F1812',
  outline: 'none', cursor: 'pointer',
};
const linkStyle = {
  flex: 1, padding: '6px 8px', borderRadius: 10,
  background: '#FBF7F0', textDecoration: 'none',
  fontSize: 10.5, color: '#1F1812', fontWeight: 600,
  textAlign: 'center',
  border: '1px solid rgba(0,0,0,0.08)',
};

function Field({ label, children }) {
  return (
    <div style={{ marginBottom: 10 }}>
      <div style={{ fontSize: 10, fontWeight: 700, color: '#6B5D4A',
                    letterSpacing: '0.06em', textTransform: 'uppercase',
                    marginBottom: 5 }}>{label}</div>
      {children}
    </div>
  );
}

// ── Phone shell (custom device frame) ───────────────────
function PhoneShell({ children, dark, tab, noFrame, hideStatus, scale = 1 }) {
  const W = 390, H = 844;
  const bg = dark ? '#0B0805' : '#F2EBE0';

  const frame = (
    <div style={{
      width: W, height: H,
      borderRadius: 50,
      background: dark ? '#000' : '#FFF',
      boxShadow: '0 40px 80px rgba(0,0,0,0.18), 0 0 0 1px rgba(0,0,0,0.12)',
      position: 'relative', overflow: 'hidden',
      fontFamily: 'Pretendard, -apple-system, system-ui, sans-serif',
      WebkitFontSmoothing: 'antialiased',
      transform: scale === 1 ? undefined : `scale(${scale})`,
      transformOrigin: 'center center',
    }}>
      {!hideStatus && (
        <React.Fragment>
          {/* Dynamic island */}
          <div style={{
            position: 'absolute', top: 11, left: '50%',
            transform: 'translateX(-50%)',
            width: 126, height: 37, borderRadius: 24, background: '#000',
            zIndex: 50,
          }}/>
          {/* Status bar */}
          <div style={{ position: 'absolute', top: 0, left: 0, right: 0, zIndex: 40 }}>
            <IOSStatusBar dark={dark}/>
          </div>
        </React.Fragment>
      )}

      {/* Content area */}
      <div style={{
        position: 'absolute', top: hideStatus ? 0 : 54, left: 0, right: 0, bottom: 0,
        background: bg,
      }}>
        <div style={{ position: 'relative', width: '100%', height: '100%' }}>
          {children}
          {tab && (
            <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, zIndex: 30 }}>
              {tab}
            </div>
          )}
        </div>
      </div>

      {/* Home indicator */}
      <div style={{
        position: 'absolute', bottom: 0, left: 0, right: 0,
        height: 34, display: 'flex', justifyContent: 'center', alignItems: 'flex-end',
        paddingBottom: 8, pointerEvents: 'none', zIndex: 80,
      }}>
        <div style={{
          width: 139, height: 5, borderRadius: 100,
          background: dark ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.28)',
        }}/>
      </div>
    </div>
  );

  if (noFrame) {
    // headless mode — just the screen content
    return (
      <div style={{
        width: W, height: H - 88, position: 'relative',
        background: bg,
        fontFamily: 'Pretendard, -apple-system, system-ui, sans-serif',
        WebkitFontSmoothing: 'antialiased',
      }}>{children}</div>
    );
  }
  return frame;
}

// ── Root ─────────────────────────────────────────────────
function App() {
  const [q, set] = useQuery();
  // Ad-boost state — survives navigation between ad flow & P12.
  // extraSlots: cumulative bonus added to today's cap. used: ad views consumed.
  const [boost, setBoost] = React.useState({ extraSlots: 0, used: 0 });
  const applyBoost = (n) => setBoost(b => ({ extraSlots: b.extraSlots + n, used: b.used + 1 }));

  // Apply theme synchronously so the very first render reads the right tokens.
  // (useEffect runs after render — would cause a 1-frame mismatch / 2-click feel.)
  applyTheme(q.theme);

  const tab = tabForScreen(q.screen);
  const showTab = hasTabBar(q.screen) && !q.hideTab;
  const dark = q.theme === 'dark';

  const tabEl = showTab && (
    <TabBar active={tab}
            onChange={(t) => set({ screen: t === 'home' ? 'P02' : 'P12', state: null })}/>
  );

  return (
    <React.Fragment>
      <DevPanel q={q} set={set}/>
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        minHeight: '100vh', padding: '40px 20px',
        background: '#ECE3D3',  // outer always light; phone interior follows theme
      }}>
        <PhoneShell dark={dark} tab={tabEl}
                    noFrame={q.noFrame} hideStatus={q.hideStatus}>
          <ScreenSwitch q={q} set={set} boost={boost} applyBoost={applyBoost}/>
        </PhoneShell>
      </div>
    </React.Fragment>
  );
}

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