/* global React, ReactDOM, TopNav, Footer, HomePage, BuildPage, GearLabPage, DataPage, BondingPage, PlatformsPage, SafetyPage, StreamerPage, ToolkitPage, DealsPage, PhoneFrame, MOBILE_VIEWS, TweaksPanel, useTweaks, TweakSection, TweakRadio, TweakSelect, TweakColor */
const { useState, useEffect } = React;

// PAGE_META: title + description + URL path per page. Drives both the
// deep-linking (URL ↔ React state) and the per-page <title>/<meta> updates.
// The CF Pages _redirects file rewrites /* → /index.html 200 so deep links
// hit this SPA without 404ing at the edge.
const PAGE_META = {
  home:      { path: '/',          title: 'livestreamers.org · the field guide & gear lab for streamers',
                                   description: 'Tested home studios and IRL rigs, bonded uplinks, data-plan strategy, platform monetization, and creator safety — for streamers everywhere.' },
  build:     { path: '/build',     title: 'Build Configurator · livestreamers.org',
                                   description: 'Pick a lane (Phone-Vertical, Sleeper, or Prestige), swap any component, get a live BOM, runtime, weight, and data strategy. Every part lab-tested.' },
  gear:      { path: '/gear',      title: 'Gear Lab · livestreamers.org',
                                   description: '184 items scored on six axes — reliability, heat, battery impact, setup difficulty, price-to-value, and IRL suitability. Affiliates disclosed on every line.' },
  data:      { path: '/data',      title: 'Data & Connectivity · livestreamers.org',
                                   description: 'Real upload speeds, real deprioritization thresholds. 34 carriers tracked. Calyx Sprout sleeper. Quarterly re-tested.' },
  bonding:   { path: '/bonding',   title: 'Cell Bonding · livestreamers.org',
                                   description: 'LiveU Solo PRO vs Peplink BR1 vs BELABOX BEE vs Speedify — head-to-head TCO, latency, recovery. The most expensive decision in your IRL stack.' },
  platforms: { path: '/platforms', title: 'Platforms · livestreamers.org',
                                   description: 'Twitch, YouTube Live, TikTok Live, Kick, Facebook Live, X Live — monetization splits, bitrate caps, vertical support. Streams Charts Q1 2026 data.' },
  safety:    { path: '/safety',    title: 'Safety & Legal · livestreamers.org',
                                   description: 'Filming consent, permits, bystander privacy, harassment, theft, travel, insurance — independent, monthly. The beat no vendor blog will run.' },
  streamer:  { path: '/streamers', title: 'Streamer Profiles · livestreamers.org',
                                   description: 'Real stacks, real economics, real failure logs. Steal-the-setup cards from the StreamerHouse living lab and 22 other profiles.' },
  toolkit:   { path: '/toolkit',   title: 'Creator Toolkit · livestreamers.org',
                                   description: 'Calculators, checklists, AI prompt packs — affiliate-free. Data usage, battery runtime, encoding profile, eligibility tracker, stream checklist.' },
  deals:     { path: '/deals',     title: 'Deals & Buyer Guides · livestreamers.org',
                                   description: 'Best-of buyer guides organised by use case. Weekly verified deals. No sponsored placement, ever.' },
};

// Reverse lookup helpers — kept tiny so the inline code in App stays clear.
const pathToPage  = (path) => Object.keys(PAGE_META).find(k => PAGE_META[k].path === path);
const pageToPath  = (key)  => PAGE_META[key]?.path || '/';

const PAGES = {
  home:      { component: HomePage,      title: 'Home' },
  build:     { component: BuildPage,     title: 'Build Configurator' },
  gear:      { component: GearLabPage,   title: 'Gear Lab' },
  data:      { component: DataPage,      title: 'Data & Connectivity' },
  bonding:   { component: BondingPage,   title: 'Cell Bonding' },
  platforms: { component: PlatformsPage, title: 'Platforms' },
  safety:    { component: SafetyPage,    title: 'Safety & Legal' },
  streamer:  { component: StreamerPage,  title: 'Streamer Profile' },
  toolkit:   { component: ToolkitPage,   title: 'Toolkit' },
  deals:     { component: DealsPage,     title: 'Deals' },
};

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "viewport": "desktop",
  "accent": "#b6ff3d"
}/*EDITMODE-END*/;

const App = () => {
  // Initial page comes from the URL path so deep-linking works on first paint.
  // typeof window guard keeps this safe in case anyone ever pre-renders this.
  const initialPage = (typeof window !== 'undefined' && pathToPage(window.location.pathname)) || 'home';
  const [page, setPageState] = useState(initialPage);
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // setPage wrapper: updates state AND pushes a history entry so the URL
  // reflects the current page. Skip pushState if URL already matches.
  const setPage = (key) => {
    if (!PAGE_META[key]) return;
    setPageState(key);
    const target = pageToPath(key);
    if (window.location.pathname !== target) {
      window.history.pushState(null, '', target);
    }
  };

  // popstate (back/forward) — sync React state to the new URL.
  useEffect(() => {
    const onPop = () => {
      const k = pathToPage(window.location.pathname);
      if (k) setPageState(k);
    };
    window.addEventListener('popstate', onPop);
    return () => window.removeEventListener('popstate', onPop);
  }, []);

  // Per-page <title> + <meta name="description">.
  // Crude but unblocks search/social previews until Phase 2's pre-render.
  useEffect(() => {
    const meta = PAGE_META[page];
    if (!meta) return;
    document.title = meta.title;
    let descTag = document.querySelector('meta[name="description"]');
    if (!descTag) {
      descTag = document.createElement('meta');
      descTag.setAttribute('name', 'description');
      document.head.appendChild(descTag);
    }
    descTag.setAttribute('content', meta.description);
    // Mirror the same to og: + twitter: tags so social previews update too.
    ['og:title', 'twitter:title'].forEach(prop => {
      const sel = prop.startsWith('og:') ? `meta[property="${prop}"]` : `meta[name="${prop}"]`;
      const el = document.querySelector(sel);
      if (el) el.setAttribute('content', meta.title);
    });
    ['og:description', 'twitter:description'].forEach(prop => {
      const sel = prop.startsWith('og:') ? `meta[property="${prop}"]` : `meta[name="${prop}"]`;
      const el = document.querySelector(sel);
      if (el) el.setAttribute('content', meta.description);
    });
    const canonical = document.querySelector('link[rel="canonical"]');
    if (canonical) canonical.setAttribute('href', 'https://livestreamers.org' + meta.path);
  }, [page]);

  // Push accent CSS var
  useEffect(() => {
    const root = document.documentElement;
    root.style.setProperty('--accent', t.accent);
    // derive related tokens
    const hex = t.accent;
    root.style.setProperty('--accent-faint', hex + '14');
    root.style.setProperty('--accent-glow', hex + '38');
    // accent ink (dark for bright, light for dim)
    root.style.setProperty('--accent-ink', '#0a0a0c');
  }, [t.accent]);

  // Scroll to top on page change
  useEffect(() => {
    window.scrollTo({ top: 0, behavior: 'instant' });
  }, [page]);

  const PageComponent = PAGES[page].component;
  const MobileView = MOBILE_VIEWS[page];

  // Three viewport modes
  if (t.viewport === 'mobile') {
    return (
      <>
        <MobileShell page={page} setPage={setPage} MobileView={MobileView} />
        <Tweaks t={t} setTweak={setTweak} />
      </>
    );
  }

  if (t.viewport === 'paired') {
    return (
      <>
        <div className="app">
          <TopNav page={page} onNav={setPage} />
          <div style={{
            display: 'grid',
            gridTemplateColumns: 'minmax(0, 1fr) 440px',
            gap: 32,
            padding: '24px 32px',
            alignItems: 'start',
          }}>
            <div style={{
              border: '1px solid var(--line)',
              borderRadius: 12,
              overflow: 'hidden',
              background: 'var(--bg-0)',
              minHeight: 600,
            }}>
              <div style={{
                padding: '10px 14px',
                background: 'var(--bg-1)',
                borderBottom: '1px solid var(--line)',
                display: 'flex', alignItems: 'center', justifyContent: 'space-between',
              }}>
                <div className="row gap-2">
                  <span style={{ width: 10, height: 10, borderRadius: '50%', background: '#ff5d6c' }} />
                  <span style={{ width: 10, height: 10, borderRadius: '50%', background: '#ffc857' }} />
                  <span style={{ width: 10, height: 10, borderRadius: '50%', background: '#b6ff3d' }} />
                </div>
                <span className="mono fs-12 text-fg4">DESKTOP · {PAGES[page].title.toUpperCase()}</span>
                <span></span>
              </div>
              <div style={{ transform: 'scale(0.62)', transformOrigin: 'top left', width: '161.3%' }}>
                <PageComponent onNav={setPage} />
              </div>
            </div>
            <div style={{ position: 'sticky', top: 100 }}>
              <div className="mb-3 row between">
                <div className="eyebrow"><span className="dot" />MOBILE COMPANION</div>
                <span className="mono fs-12 text-fg4">{PAGES[page].title.toUpperCase()}</span>
              </div>
              <PhoneFrame page={page}>
                <MobileView onNav={setPage} />
              </PhoneFrame>
            </div>
          </div>
        </div>
        <Tweaks t={t} setTweak={setTweak} />
      </>
    );
  }

  // Desktop default
  return (
    <>
      <div className="app">
        <TopNav page={page} onNav={setPage} />
        <main>
          <PageComponent onNav={setPage} />
        </main>
        <Footer onNav={setPage} />
      </div>
      <Tweaks t={t} setTweak={setTweak} />
    </>
  );
};

const MobileShell = ({ page, setPage, MobileView }) => (
  <div style={{
    minHeight: '100vh',
    display: 'grid',
    placeItems: 'center',
    padding: 24,
    background: 'radial-gradient(800px 500px at 50% 0%, rgba(182,255,61,0.04), transparent 60%), var(--bg-0)',
  }}>
    <div className="col gap-4" style={{ alignItems: 'center' }}>
      <div className="row gap-2">
        {Object.keys(PAGES).map(k => (
          <button key={k} onClick={() => setPage(k)}
            className={`pill ${page === k ? 'is-on' : ''}`}>
            {PAGES[k].title}
          </button>
        ))}
      </div>
      <PhoneFrame page={page}>
        <MobileView onNav={setPage} />
      </PhoneFrame>
    </div>
  </div>
);

const Tweaks = ({ t, setTweak }) => (
  <TweaksPanel title="Tweaks">
    <TweakSection title="Viewport mode">
      <TweakRadio
        value={t.viewport}
        onChange={(v) => setTweak('viewport', v)}
        options={[
          { value: 'desktop', label: 'Desktop' },
          { value: 'paired',  label: 'Paired' },
          { value: 'mobile',  label: 'Mobile' },
        ]} />
    </TweakSection>
    <TweakSection title="Accent">
      <TweakColor
        value={t.accent}
        onChange={(v) => setTweak('accent', v)}
        options={['#b6ff3d', '#ff2d6f', '#5ec8ff', '#9146ff']} />
    </TweakSection>
  </TweaksPanel>
);

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