/* App entry — wires Tweaks, Cursor, Audio toggle, Scroll progress */

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "void",
  "motion": "alive",
  "accentBoost": 1,
  "ambientAudio": false,
  "density": "default"
}/*EDITMODE-END*/;

const App = () => {
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [audioOn, setAudioOn] = React.useState(false);
  const [scrollPct, setScrollPct] = React.useState(0);

  // Apply theme class
  React.useEffect(() => {
    document.body.classList.remove("theme-void", "theme-paper", "theme-cosmos");
    document.body.classList.add(`theme-${tweaks.theme}`);
  }, [tweaks.theme]);

  React.useEffect(() => {
    document.body.dataset.motion = tweaks.motion;
  }, [tweaks.motion]);

  // Cursor follower
  React.useEffect(() => {
    const dot = document.querySelector(".cursor-dot");
    const ring = document.querySelector(".cursor-ring");
    if (!dot || !ring) return;
    let rx = 0, ry = 0, dx = 0, dy = 0;
    const onMove = (e) => {
      dx = e.clientX; dy = e.clientY;
      dot.style.transform = `translate(${dx}px, ${dy}px) translate(-50%, -50%)`;
      const target = e.target;
      if (target && target.closest && target.closest('[data-cursor="hover"], a, button')) {
        document.body.classList.add("cursor-hover");
      } else {
        document.body.classList.remove("cursor-hover");
      }
    };
    let raf;
    const animate = () => {
      rx += (dx - rx) * 0.18;
      ry += (dy - ry) * 0.18;
      ring.style.transform = `translate(${rx}px, ${ry}px) translate(-50%, -50%)`;
      raf = requestAnimationFrame(animate);
    };
    animate();
    window.addEventListener("mousemove", onMove);
    return () => {
      window.removeEventListener("mousemove", onMove);
      cancelAnimationFrame(raf);
    };
  }, []);

  // Scroll progress
  React.useEffect(() => {
    const onScroll = () => {
      const h = document.documentElement;
      const total = h.scrollHeight - h.clientHeight;
      setScrollPct(total > 0 ? (h.scrollTop / total) * 100 : 0);
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  // Reveal observer
  React.useEffect(() => {
    const els = document.querySelectorAll(".reveal");
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) e.target.classList.add("in");
      });
    }, { threshold: 0.12 });
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, []);

  // Auto-start ambient audio on first user interaction
  React.useEffect(() => {
    if (audioOn) return;
    const start = () => {
      setAudioOn(true);
      cleanup();
    };
    const cleanup = () => {
      window.removeEventListener("pointerdown", start);
      window.removeEventListener("keydown", start);
      window.removeEventListener("scroll", start);
      window.removeEventListener("touchstart", start);
      window.removeEventListener("mousemove", start);
    };
    window.addEventListener("pointerdown", start, { once: true });
    window.addEventListener("keydown", start, { once: true });
    window.addEventListener("scroll", start, { once: true, passive: true });
    window.addEventListener("touchstart", start, { once: true, passive: true });
    window.addEventListener("mousemove", start, { once: true, passive: true });
    return cleanup;
  }, []);

  // Ambient audio (Web Audio API — drone)
  const audioCtxRef = React.useRef(null);
  const oscNodesRef = React.useRef([]);
  React.useEffect(() => {
    if (!audioOn) {
      // teardown
      if (audioCtxRef.current) {
        try {
          oscNodesRef.current.forEach(n => { try { n.stop(); } catch(e){} });
          audioCtxRef.current.close();
        } catch (e) {}
        audioCtxRef.current = null;
        oscNodesRef.current = [];
      }
      return;
    }
    const Ctx = window.AudioContext || window.webkitAudioContext;
    if (!Ctx) return;
    const ctx = new Ctx();
    audioCtxRef.current = ctx;
    const master = ctx.createGain();
    master.gain.value = 0;
    master.gain.linearRampToValueAtTime(0.06, ctx.currentTime + 2.5);
    master.connect(ctx.destination);

    // 432Hz-anchored drone — 3 detuned sines
    const freqs = [108, 162, 216];
    freqs.forEach((f, i) => {
      const osc = ctx.createOscillator();
      const g = ctx.createGain();
      osc.type = "sine";
      osc.frequency.value = f;
      g.gain.value = 0.3;
      // slow LFO on gain
      const lfo = ctx.createOscillator();
      const lfoGain = ctx.createGain();
      lfo.frequency.value = 0.05 + i * 0.03;
      lfoGain.gain.value = 0.15;
      lfo.connect(lfoGain);
      lfoGain.connect(g.gain);
      osc.connect(g);
      g.connect(master);
      osc.start();
      lfo.start();
      oscNodesRef.current.push(osc, lfo);
    });

    return () => {
      try {
        master.gain.linearRampToValueAtTime(0, ctx.currentTime + 0.4);
        setTimeout(() => {
          oscNodesRef.current.forEach(n => { try { n.stop(); } catch(e){} });
          try { ctx.close(); } catch (e) {}
        }, 500);
      } catch (e) {}
    };
  }, [audioOn]);

  return (
    <>
      <div className="cursor-ring" />
      <div className="cursor-dot" />
      <div className="scroll-rail" style={{ width: `${scrollPct}%` }} />

      {/* Cosmos field — vast universe with worlds, galaxies, nebulae & stars */}
      <div className="cosmos-field">
        <div className="cosmos-grid" />
        {tweaks.theme !== "paper" && <div className="cosmos-stars-far" />}
        {tweaks.theme !== "paper" && <div className="cosmos-stars-mid" />}
        {tweaks.theme !== "paper" && <div className="cosmos-stars-near" />}
        {tweaks.theme !== "paper" && <div className="cosmos-stars-extra-1" />}
        {tweaks.theme !== "paper" && <div className="cosmos-stars-extra-2" />}
        {tweaks.theme !== "paper" && <div className="cosmos-stars-extra-3" />}
        {tweaks.theme !== "paper" && <div className="universe universe-spiral-1" />}
        {tweaks.theme !== "paper" && <div className="universe universe-elliptical" />}
        {tweaks.theme !== "paper" && <div className="universe universe-nebula-1" />}
        {tweaks.theme !== "paper" && <div className="universe universe-nebula-2" />}
        {tweaks.theme !== "paper" && <div className="universe universe-nebula-3" />}
        {tweaks.theme !== "paper" && <div className="star-cluster star-cluster-1" />}
        {tweaks.theme !== "paper" && <div className="star-cluster star-cluster-2" />}
        {tweaks.theme !== "paper" && <div className="comet comet-1" />}
        {tweaks.theme !== "paper" && <div className="comet comet-2" />}
        {tweaks.theme !== "paper" && <div className="comet comet-3" />}
        <div className="cosmos-grain" />
        <div className="cosmos-vignette" />
      </div>

      <Nav />
      <main>
        <Hero />
        <Marquee />
        <CoreStatement />
        <VisionStatement />
        <WhatWeDo />
        <WhyThisMatters />
        <OurApproach />
        <CurrentEcosystem />
        <LongTerm />
        <Investor />
        <Closing />
      </main>
      <Footer />

      <button
        className={`audio-toggle ${audioOn ? "" : "audio-paused"}`}
        onClick={() => setAudioOn((v) => !v)}
        data-cursor="hover"
      >
        <div className="audio-bars">
          <span /><span /><span /><span />
        </div>
        <span>{audioOn ? "Ambient · ON" : "Ambient · OFF"}</span>
      </button>

      <TweaksPanel title="Tweaks" defaultPosition={{ right: 24, bottom: 80 }}>
        <TweakSection title="Theme">
          <TweakRadio
            label="Surface"
            value={tweaks.theme}
            options={[
              { value: "void", label: "Void" },
              { value: "cosmos", label: "Cosmos" },
              { value: "paper", label: "Paper" },
            ]}
            onChange={(v) => setTweak("theme", v)}
          />
        </TweakSection>
        <TweakSection title="Motion">
          <TweakRadio
            label="Atmosphere"
            value={tweaks.motion}
            options={[
              { value: "still", label: "Still" },
              { value: "subtle", label: "Subtle" },
              { value: "alive", label: "Alive" },
            ]}
            onChange={(v) => setTweak("motion", v)}
          />
        </TweakSection>
        <TweakSection title="Density">
          <TweakRadio
            label="Spacing"
            value={tweaks.density}
            options={[
              { value: "compact", label: "Compact" },
              { value: "default", label: "Default" },
              { value: "airy", label: "Airy" },
            ]}
            onChange={(v) => setTweak("density", v)}
          />
        </TweakSection>
        <TweakSection title="Accent boost">
          <TweakSlider
            label="Saturation"
            min={0.4} max={1.6} step={0.1}
            value={tweaks.accentBoost}
            onChange={(v) => setTweak("accentBoost", v)}
          />
        </TweakSection>
      </TweaksPanel>

      {/* Density / motion / accent style overrides */}
      <style>{`
        body[data-motion="still"] .cosmos-mesh,
        body[data-motion="still"] .cosmos-stars,
        body[data-motion="still"] .marquee-track {
          animation: none !important;
        }
        body[data-motion="subtle"] .cosmos-mesh { animation-duration: 80s !important; }
        body[data-motion="subtle"] .cosmos-stars { animation: none !important; }

        body[data-density="compact"] .section-pad { padding: 72px 0; }
        body[data-density="airy"] .section-pad { padding: 160px 0; }

        :root {
          --magenta: oklch(0.66 ${0.22 * tweaks.accentBoost} 0deg);
          --teal: oklch(0.78 ${0.16 * tweaks.accentBoost} 195deg);
          --gold: oklch(0.78 ${0.12 * tweaks.accentBoost} 80deg);
        }
      `}</style>
    </>
  );
};

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