// Composer. Owns scroll-progress (drives the traveling node), the reveal observer, the
// reduced-motion flag and theme toggle, then mounts the four acts + the integrated network.

const { useState: useStateA, useEffect: useEffectA, useRef: useRefA } = React;

const PREFERS_REDUCED = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

// boot plays once per browser; return visits go straight to the hero
function hasBooted() { try { return !!localStorage.getItem('wb_booted'); } catch (e) { return false; } }
function markBooted() { try { localStorage.setItem('wb_booted', '1'); } catch (e) {} }

function App() {
  const { NavBar } = window.WollenbergUIKit;
  const Network = window.Network;

  const [progress, setProgress] = useStateA(0);
  const [bootDone, setBootDone] = useStateA(hasBooted());
  const [isDark, setIsDark] = useStateA(true);

  // scroll → progress (0 at top, 1 at contact), drives the traveling node. Updated directly
  // from the scroll event (not a self-sustaining rAF loop, which throttles when not painting);
  // visual smoothing comes from the CSS transition on the node itself.
  useEffectA(() => {
    const read = () => {
      const max = (document.documentElement.scrollHeight - window.innerHeight) || 1;
      const p = Math.min(1, Math.max(0, window.scrollY / max));
      setProgress((prev) => (Math.abs(prev - p) > 0.0008 ? p : prev));
    };
    read();
    window.addEventListener('scroll', read, { passive: true });
    window.addEventListener('resize', read);
    return () => { window.removeEventListener('scroll', read); window.removeEventListener('resize', read); };
  }, []);

  // reveal .wb-reveal elements by scroll position — robust where IntersectionObserver
  // is throttled (capture/headless contexts). Guaranteed initial + safety reveal.
  useEffectA(() => {
    let els = [];
    let raf;
    const collect = () => { els = Array.from(document.querySelectorAll('.wb-reveal:not([data-in="true"])')); };
    const check = () => {
      cancelAnimationFrame(raf);
      raf = requestAnimationFrame(() => {
        const trigger = window.innerHeight * 0.9;
        let remaining = false;
        els.forEach((el) => {
          if (el.getAttribute('data-in') === 'true') return;
          const top = el.getBoundingClientRect().top;
          if (top < trigger) el.setAttribute('data-in', 'true'); else remaining = true;
        });
        if (remaining) collect();
      });
    };
    const revealAll = () => document.querySelectorAll('.wb-reveal').forEach((el) => el.setAttribute('data-in', 'true'));

    if (PREFERS_REDUCED) { revealAll(); return; }
    collect();
    check();
    window.addEventListener('scroll', check, { passive: true });
    window.addEventListener('resize', check);
    const safety = window.setTimeout(revealAll, 2600); // never leave content hidden
    return () => { window.removeEventListener('scroll', check); window.removeEventListener('resize', check); window.clearTimeout(safety); cancelAnimationFrame(raf); };
  }, [bootDone]);

  const toggleTheme = () => {
    setIsDark((d) => {
      const next = !d;
      if (next) document.documentElement.removeAttribute('data-theme');
      else document.documentElement.setAttribute('data-theme', 'light');
      return next;
    });
  };

  const navLinks = [
    { label: 'The Node', href: '#node' },
    { label: 'Systems', href: '#systems' },
    { label: 'Blog', href: '#systems', building: true },
    { label: 'Contact', href: '#contact' },
  ];

  return (
    <React.Fragment>
      {!bootDone && <Boot reduced={PREFERS_REDUCED} onDone={() => { markBooted(); setBootDone(true); }} />}

      <div className="wb-net-layer">
        <Network progress={progress} reduced={PREFERS_REDUCED} />
      </div>

      <div className="wb-content">
        <div className="wb-nav-wrap">
          <div className="wb-shell">
            <NavBar
              brandName="wollenberg.dev"
              links={navLinks}
              isDark={isDark}
              onToggleTheme={toggleTheme}
              cta={{ label: 'Hire on Upwork ↗', href: WB.meta.upwork }}
            />
          </div>
        </div>

        <main>
          <Hero />
          <TheNode />
          <Systems />
          <Handoff />
        </main>
      </div>
    </React.Fragment>
  );
}

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