// app.jsx — main App for Juan David's personal site

const { useState, useEffect, useRef } = React;

function useReveal() {
  useEffect(() => {
    const els = document.querySelectorAll("[data-reveal], [data-reveal-stagger]");
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) {
          e.target.classList.add("in");
          io.unobserve(e.target);
        }
      });
    }, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" });
    els.forEach(el => io.observe(el));
    return () => io.disconnect();
  });
}

function useCursor(enabled) {
  useEffect(() => {
    const dot = document.getElementById("cursor-dot");
    if (!dot) return;
    if (!enabled) { dot.classList.remove("on"); return; }
    let raf = 0;
    const move = (e) => {
      cancelAnimationFrame(raf);
      raf = requestAnimationFrame(() => {
        dot.style.transform = `translate(${e.clientX}px, ${e.clientY}px) translate(-50%,-50%)`;
        dot.classList.add("on");
      });
    };
    const over = (e) => {
      const t = e.target;
      const interactive = t && (t.closest("a, button, input, label, [role='button']"));
      dot.classList.toggle("lg", !!interactive);
    };
    window.addEventListener("mousemove", move);
    window.addEventListener("mouseover", over);
    return () => { window.removeEventListener("mousemove", move); window.removeEventListener("mouseover", over); };
  }, [enabled]);
}

const ACCENT_OPTS = [
  { id: "amber",  value: "oklch(0.78 0.14 75)",  label: "Amber" },
  { id: "bone",   value: "oklch(0.92 0.02 80)",  label: "Bone" },
  { id: "moss",   value: "oklch(0.74 0.13 145)", label: "Moss" },
  { id: "indigo", value: "oklch(0.68 0.16 270)", label: "Indigo" },
  { id: "rust",   value: "oklch(0.66 0.16 35)",  label: "Rust" },
];

function App() {
  const [t, setTweak] = useTweaks(window.TWEAK_DEFAULTS);
  const [lang, setLang] = useState(t.lang || "es");

  useReveal();
  useCursor(t.showCursor);

  // Apply CSS vars from tweaks
  useEffect(() => {
    document.documentElement.style.setProperty("--accent", t.accent);
    document.body.dataset.density = t.density;
  }, [t.accent, t.density]);

  // Sync html lang and persist
  useEffect(() => {
    document.documentElement.lang = lang;
    setTweak("lang", lang);
  }, [lang]);

  const copy = window.COPY[lang];
  const mode = t.displayMode;

  const tw = copy.tweaks;
  const accentSwatchOpts = ACCENT_OPTS.map(a => a.value);

  return (
    <React.Fragment>
      <TopBar lang={lang} setLang={setLang} copy={copy}/>
      <main>
        <Hero copy={copy} mode={mode}/>
        <About copy={copy} mode={mode}/>
        <Tools copy={copy} mode={mode}/>
        <Marquee lang={lang}/>
        <Services copy={copy} mode={mode}/>
        <Expertise copy={copy} mode={mode}/>
        <Projects copy={copy} mode={mode}/>
        <Stack copy={copy} mode={mode}/>
        <Experience copy={copy} mode={mode}/>
        <Others copy={copy} mode={mode}/>
        <BreakEvenDemo copy={copy} lang={lang}/>
        <Contact copy={copy} mode={mode}/>
      </main>
      <Footer copy={copy}/>

      <TweaksPanel title={tw.title}>
        <TweakSection label={tw.visual}/>
        <TweakColor label={tw.accent} value={t.accent}
          options={accentSwatchOpts}
          onChange={(v) => setTweak("accent", v)}/>
        <TweakRadio label={tw.density} value={t.density}
          options={tw.densityOpts}
          onChange={(v) => setTweak("density", v)}/>
        <TweakRadio label={tw.display} value={t.displayMode}
          options={tw.displayOpts}
          onChange={(v) => setTweak("displayMode", v)}/>
        <TweakToggle label={tw.cursor} value={t.showCursor}
          onChange={(v) => setTweak("showCursor", v)}/>
        <TweakSection label={tw.lang}/>
        <TweakRadio label={tw.lang} value={lang}
          options={["es","en"]}
          onChange={(v) => setLang(v)}/>
      </TweaksPanel>
    </React.Fragment>
  );
}

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