// Main app — wires nav, sections, footer, tweaks panel, cursor and scroll plumbing.

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "heroVariant": "manifesto",
  "ofertasLayout": "list",
  "accent": "oxblood",
  "bodyFont": "Inter Tight",
  "showCursor": true,
  "showSideProgress": true,
  "paperGrain": true
}/*EDITMODE-END*/;

function FuseCursor() {
  React.useEffect(() => {
    const dot = document.getElementById('fuse-cursor');
    if (!dot) return;

    let x = window.innerWidth / 2, y = window.innerHeight / 2;
    let tx = x, ty = y;
    let raf;

    const tick = () => {
      // small easing for buttery feel
      x += (tx - x) * 0.28;
      y += (ty - y) * 0.28;
      dot.style.transform = `translate(${x}px, ${y}px) translate(-50%, -50%)`;
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);

    const onMove = (e) => {
      tx = e.clientX; ty = e.clientY;
      if (!dot.classList.contains('ready')) dot.classList.add('ready');
    };
    const onOver = (e) => {
      const t = e.target;
      if (!t) return;
      const isLink = t.closest && (t.closest('a, button, [role="button"], .diag-option, .offer-row, .leak-card, label, input, textarea'));
      const isText = t.closest && t.closest('input, textarea');
      const onDark = t.closest && t.closest('.dark, .surface-dark, footer, #porque, .diag-result-card');
      dot.classList.toggle('hover', !!isLink && !isText);
      dot.classList.toggle('text', !!isText);
      dot.classList.toggle('on-dark', !!onDark);
    };
    const onLeave = () => dot.classList.remove('ready');

    window.addEventListener('mousemove', onMove, { passive: true });
    document.addEventListener('mouseover', onOver, true);
    document.addEventListener('mouseleave', onLeave);

    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener('mousemove', onMove);
      document.removeEventListener('mouseover', onOver, true);
      document.removeEventListener('mouseleave', onLeave);
    };
  }, []);
  return null;
}

function ScrollProgress() {
  React.useEffect(() => {
    const el = document.getElementById('scroll-progress');
    if (!el) return;
    let raf;
    const onScroll = () => {
      cancelAnimationFrame(raf);
      raf = requestAnimationFrame(() => {
        const h = document.documentElement;
        const pct = h.scrollTop / Math.max(1, h.scrollHeight - h.clientHeight);
        el.style.width = `${pct * 100}%`;
      });
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => { window.removeEventListener('scroll', onScroll); cancelAnimationFrame(raf); };
  }, []);
  return null;
}

function SideProgress() {
  const [lang] = useLang();
  const [activeIdx, setActiveIdx] = React.useState(0);
  const [onDark, setOnDark] = React.useState(false);
  const sections = React.useMemo(() => ([
    { id: 'top', es: 'Inicio', en: 'Top' },
    { id: 'propuesta', es: 'Propuesta', en: 'Thesis' },
    { id: 'paraquien', es: 'Para quién', en: 'Who' },
    { id: 'ofertas', es: 'Ofertas', en: 'Offerings' },
    { id: 'diagnostico', es: 'Diagnóstico', en: 'Diagnostic' },
    { id: 'proceso', es: 'Proceso', en: 'Process' },
    { id: 'porque', es: 'Por qué', en: 'Why' },
    { id: 'cta', es: 'Hablar', en: 'Talk' },
  ]), []);

  React.useEffect(() => {
    const update = () => {
      const cy = window.innerHeight / 2;
      let best = 0, bestDist = Infinity;
      sections.forEach((s, i) => {
        const el = document.getElementById(s.id);
        if (!el) return;
        const r = el.getBoundingClientRect();
        const mid = r.top + r.height / 2;
        const d = Math.abs(mid - cy);
        if (d < bestDist) { bestDist = d; best = i; }
      });
      setActiveIdx(best);

      // Dark-mode detection: which section is at midline?
      const probe = document.elementFromPoint(window.innerWidth - 60, window.innerHeight / 2);
      const darkAncestor = probe && probe.closest && probe.closest('.dark, footer');
      setOnDark(!!darkAncestor);
    };
    update();
    window.addEventListener('scroll', update, { passive: true });
    window.addEventListener('resize', update);
    return () => {
      window.removeEventListener('scroll', update);
      window.removeEventListener('resize', update);
    };
  }, [sections]);

  return (
    <nav className={`side-progress ${onDark ? 'on-dark' : ''}`} aria-label="Section progress">
      {sections.map((s, i) => (
        <a key={s.id} href={`#${s.id}`} className={i === activeIdx ? 'active' : ''}>
          <span className="dot" />
          <span className="lbl">{s[lang]}</span>
        </a>
      ))}
    </nav>
  );
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // Sync accent palette to html data-attr
  React.useEffect(() => {
    document.documentElement.setAttribute('data-accent', t.accent);
  }, [t.accent]);

  // Body sans override — applied as a CSS variable so we can audition
  // different humanist sans against Instrument Serif without touching
  // the design system file.
  React.useEffect(() => {
    document.documentElement.style.setProperty(
      '--font-sans',
      `'${t.bodyFont}', 'Helvetica Neue', Helvetica, Arial, sans-serif`
    );
  }, [t.bodyFont]);

  // Paper grain body class
  React.useEffect(() => {
    document.body.classList.toggle('paper-grain', !!t.paperGrain);
  }, [t.paperGrain]);

  // Scroll reveal — toggle `.in` on .reveal and .reveal-left as they enter viewport
  React.useEffect(() => {
    const io = new IntersectionObserver((entries) => {
      for (const e of entries) {
        if (e.isIntersecting) {
          e.target.classList.add('in');
          io.unobserve(e.target);
        }
      }
    }, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' });

    const observe = () => {
      document.querySelectorAll('.reveal:not(.in), .reveal-left:not(.in)').forEach(el => io.observe(el));
    };
    observe();
    // Also observe after each render burst (eg after Diagnostico mounts result)
    const mo = new MutationObserver(observe);
    mo.observe(document.body, { childList: true, subtree: true });

    return () => { io.disconnect(); mo.disconnect(); };
  }, []);

  return (
    <>
      <div className="scroll-progress" id="scroll-progress" />
      {t.showCursor && <FuseCursor />}
      <ScrollProgress />
      <Nav />
      {t.showSideProgress && <SideProgress />}
      <main>
        <Hero variant={t.heroVariant} />
        <Propuesta />
        <ParaQuien />
        <Ofertas variant={t.ofertasLayout} />
        <Diagnostico />
        <Proceso />
        <PorQue />
        <CTA />
      </main>
      <Footer />

      <TweaksPanel title="Tweaks">
        <TweakSection label="Hero">
          <TweakSelect
            label="Variant"
            value={t.heroVariant}
            onChange={(v) => setTweak('heroVariant', v)}
            options={[
              { value: 'manifesto', label: 'Manifesto' },
              { value: 'operativo', label: 'Operativo (caso)' },
              { value: 'pregunta', label: 'Pregunta' },
            ]}
          />
        </TweakSection>

        <TweakSection label="Ofertas">
          <TweakRadio
            label="Layout"
            value={t.ofertasLayout}
            onChange={(v) => setTweak('ofertasLayout', v)}
            options={[
              { value: 'list', label: 'Lista' },
              { value: 'grid', label: 'Grid' },
              { value: 'table', label: 'Tabla' },
            ]}
          />
        </TweakSection>

        <TweakSection label="Paleta">
          <TweakRadio
            label="Acento"
            value={t.accent}
            onChange={(v) => setTweak('accent', v)}
            options={[
              { value: 'oxblood', label: 'Oxblood' },
              { value: 'ochre', label: 'Ochre' },
            ]}
          />
        </TweakSection>

        <TweakSection label="Tipografía">
          <TweakSelect
            label="Body sans"
            value={t.bodyFont}
            onChange={(v) => setTweak('bodyFont', v)}
            options={[
              { value: 'Inter Tight', label: 'Inter Tight' },
              { value: 'IBM Plex Sans', label: 'IBM Plex Sans' },
              { value: 'Manrope', label: 'Manrope' },
            ]}
          />
        </TweakSection>

        <TweakSection label="Detalles">
          <TweakToggle
            label="Cursor editorial"
            value={t.showCursor}
            onChange={(v) => setTweak('showCursor', v)}
          />
          <TweakToggle
            label="Side progress"
            value={t.showSideProgress}
            onChange={(v) => setTweak('showSideProgress', v)}
          />
          <TweakToggle
            label="Paper grain"
            value={t.paperGrain}
            onChange={(v) => setTweak('paperGrain', v)}
          />
        </TweakSection>
      </TweaksPanel>
    </>
  );
}

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