const {
  useState, useEffect, useRef,
  Nav, Hero, Marquee, StatsBlock, Pillars, Demo, TimelineSection,
  Calculator, Compare, Pricing, FAQ, FinalCTA, Footer, TweaksPanel,
  Icon, LandingStatsProvider,
} = window;

/* ─── Sticky CTA : apparaît en bas-droite quand le hero-CTA sort du viewport ─── */
function StickyCTA() {
  const [visible, setVisible] = useState(false);
  const [pricingReached, setPricingReached] = useState(false);

  useEffect(() => {
    const sentinel = document.getElementById('hero-cta-sentinel');
    if (!sentinel) return;
    const obs = new IntersectionObserver(([entry]) => {
      setVisible(!entry.isIntersecting);
    }, { rootMargin: '0px 0px -20% 0px', threshold: 0 });
    obs.observe(sentinel);
    return () => obs.disconnect();
  }, []);

  useEffect(() => {
    const pricing = document.getElementById('pricing');
    if (!pricing) return;
    // Sentinel placé à la fin de la section pricing
    const sentinel = document.createElement('div');
    sentinel.style.cssText = 'position:absolute;bottom:0;height:1px;width:1px;pointer-events:none';
    pricing.style.position = 'relative';
    pricing.appendChild(sentinel);
    // Dès que ce sentinel dépasse le haut du viewport → on est en dessous de pricing
    const obs = new IntersectionObserver(([entry]) => {
      // boundingClientRect.top < 0 = sentinel sorti par le haut = on a dépassé pricing
      setPricingReached(entry.boundingClientRect.top < window.innerHeight);
    }, { threshold: 0 });
    obs.observe(sentinel);
    return () => { obs.disconnect(); sentinel.remove(); };
  }, []);

  const show = visible && !pricingReached;

  return (
    <a
      href="#pricing"
      aria-label="Rejoindre maintenant"
      data-cursor="hover"
      style={{
        position: 'fixed',
        right: 24,
        bottom: 24,
        zIndex: 95,
        display: 'inline-flex',
        alignItems: 'center',
        gap: 10,
        padding: '14px 22px 14px 20px',
        borderRadius: 999,
        background: 'var(--accent)',
        color: '#ffffff',
        fontSize: 14,
        fontWeight: 600,
        letterSpacing: '-0.005em',
        textDecoration: 'none',
        boxShadow: '0 12px 40px -10px var(--accent-glow), 0 0 0 1px color-mix(in oklab, var(--accent) 40%, transparent)',
        opacity: show ? 1 : 0,
        transform: show
          ? 'translate(0, 0) scale(1)'
          : 'translate(16px, 20px) scale(0.92)',
        pointerEvents: show ? 'auto' : 'none',
        filter: show ? 'blur(0)' : 'blur(4px)',
        transition:
          'opacity 0.55s cubic-bezier(.2,.7,.2,1), transform 0.55s cubic-bezier(.2,.7,.2,1), filter 0.55s cubic-bezier(.2,.7,.2,1), box-shadow 0.3s ease',
      }}
      onMouseEnter={(e) => {
        e.currentTarget.style.boxShadow =
          '0 16px 48px -8px var(--accent-glow), 0 0 0 4px color-mix(in oklab, var(--accent) 25%, transparent)';
        e.currentTarget.style.transform = 'translate(0, -2px) scale(1.02)';
      }}
      onMouseLeave={(e) => {
        e.currentTarget.style.boxShadow =
          '0 12px 40px -10px var(--accent-glow), 0 0 0 1px color-mix(in oklab, var(--accent) 40%, transparent)';
        e.currentTarget.style.transform = 'translate(0, 0) scale(1)';
      }}
    >
      <span style={{
        width: 8, height: 8, borderRadius: '50%',
        background: '#fff',
        boxShadow: '0 0 10px rgba(255,255,255,0.8)',
        animation: 'breathe 2s ease-in-out infinite',
      }} />
      Rejoindre maintenant
      <Icon.Arrow size={14} />
    </a>
  );
}

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "dark",
  "density": "normal",
  "heroVariant": "orb",
  "accentHue": 155
}/*EDITMODE-END*/;

function App() {
  const [theme, setTheme] = useState(() => {
    try { const s = localStorage.getItem('ds-theme'); return s === 'light' || s === 'dark' ? s : TWEAK_DEFAULTS.theme; } catch { return TWEAK_DEFAULTS.theme; }
  });
  const [density, setDensity] = useState(TWEAK_DEFAULTS.density);
  const [heroVariant, setHeroVariant] = useState(TWEAK_DEFAULTS.heroVariant);
  const [accentHue, setAccentHue] = useState(TWEAK_DEFAULTS.accentHue);
  const [tweaksOn, setTweaksOn] = useState(false);

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme);
    try { localStorage.setItem('ds-theme', theme); } catch {}
    document.documentElement.setAttribute('data-density', density);
    document.documentElement.style.setProperty('--accent', `oklch(0.78 0.18 ${accentHue})`);
    document.documentElement.style.setProperty('--accent-deep', `oklch(0.62 0.17 ${accentHue})`);
    document.documentElement.style.setProperty('--accent-soft', `oklch(0.88 0.10 ${accentHue})`);
    document.documentElement.style.setProperty('--accent-glow', `oklch(0.78 0.18 ${accentHue} / 0.35)`);
    if (theme === 'light') {
      document.documentElement.style.setProperty('--accent', `oklch(0.62 0.17 ${accentHue})`);
    }
  }, [theme, density, accentHue]);

  // Transition animée light/dark — cercle qui part du bas-gauche et recouvre le site
  const setThemeAnimated = (newTheme) => {
    if (newTheme === theme) return;
    const prefersReduced = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;
    if (prefersReduced) { setTheme(newTheme); persist({ theme: newTheme }); return; }

    // Couleur cible = fond du nouveau thème
    const targetBg = newTheme === 'light' ? '#f7f7f5' : '#0a0a0b';

    const overlay = document.createElement('div');
    overlay.style.cssText = `
      position: fixed; inset: 0; z-index: 9998; pointer-events: none;
      background: ${targetBg};
      clip-path: circle(0px at 0% 100%);
      will-change: clip-path, opacity;
      transition: clip-path 900ms cubic-bezier(0.77, 0, 0.175, 1);
    `;
    document.body.appendChild(overlay);

    // Lance l'expansion
    requestAnimationFrame(() => {
      overlay.style.clipPath = 'circle(220vmax at 0% 100%)';
    });

    // Swap du thème juste avant la fin → aucun flash
    window.setTimeout(() => {
      setTheme(newTheme);
      persist({ theme: newTheme });
    }, 860);

    // Fade out de l'overlay une fois le thème appliqué
    window.setTimeout(() => {
      overlay.style.transition = 'opacity 380ms ease';
      requestAnimationFrame(() => { overlay.style.opacity = '0'; });
      window.setTimeout(() => overlay.remove(), 420);
    }, 920);
  };

  // Tweaks host protocol
  useEffect(() => {
    const listener = (e) => {
      if (e.data?.type === '__activate_edit_mode') setTweaksOn(true);
      if (e.data?.type === '__deactivate_edit_mode') setTweaksOn(false);
    };
    window.addEventListener('message', listener);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', listener);
  }, []);

  // Persist tweak keys
  const persist = (patch) => {
    window.parent.postMessage({ type: '__edit_mode_set_keys', edits: patch }, '*');
  };

  // Cursor — desktop (pointer: fine) only, réagit aux changements de media query
  useEffect(() => {
    let dot, ring, ri, raf, mx = 0, my = 0, rx = 0, ry = 0;
    let active = false;

    const onMove = (e) => { mx = e.clientX; my = e.clientY; };
    const onOver = (e) => {
      if (!ring) return;
      const t = e.target.closest('a, button, [data-cursor="hover"], input, select, [role="button"]');
      ring.classList.toggle('vz-cursor-ring--hover', !!t);
    };
    const onDown = () => ring && ring.classList.add('vz-cursor-ring--click');
    const onUp   = () => ring && ring.classList.remove('vz-cursor-ring--click');

    const tick = () => {
      if (dot) dot.style.transform = `translate(${mx}px,${my}px)`;
      rx += (mx - rx) * 0.1;
      ry += (my - ry) * 0.1;
      if (ring) ring.style.transform = `translate(${rx}px,${ry}px)`;
      raf = requestAnimationFrame(tick);
    };

    const mount = () => {
      if (active) return;
      active = true;
      dot = document.createElement('div');
      ring = document.createElement('div');
      ri = document.createElement('div');
      dot.className  = 'vz-cursor-dot';
      ring.className = 'vz-cursor-ring';
      ri.className   = 'vz-cursor-ring-inner';
      ring.appendChild(ri);
      document.body.appendChild(dot);
      document.body.appendChild(ring);
      raf = requestAnimationFrame(tick);
      window.addEventListener('mousemove', onMove);
      window.addEventListener('mouseover', onOver);
      window.addEventListener('mousedown', onDown);
      window.addEventListener('mouseup',   onUp);
    };

    const unmount = () => {
      if (!active) return;
      active = false;
      cancelAnimationFrame(raf);
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseover', onOver);
      window.removeEventListener('mousedown', onDown);
      window.removeEventListener('mouseup',   onUp);
      dot && dot.remove();
      ring && ring.remove();
      dot = ring = ri = null;
    };

    const mq = window.matchMedia('(hover: hover) and (pointer: fine)');
    const onChange = (e) => e.matches ? mount() : unmount();

    mq.addEventListener('change', onChange);
    if (mq.matches) mount();

    return () => {
      mq.removeEventListener('change', onChange);
      unmount();
    };
  }, []);

  return (
    <LandingStatsProvider>
      <Nav theme={theme} setTheme={setThemeAnimated} />
      <Hero variant={heroVariant} />
      <StatsBlock />
      <Pillars />
      <Marquee />
      <Demo />
      <Compare />
      <TimelineSection />
      <Calculator />
      <Pricing />
      <FAQ />
      <FinalCTA />
      <Footer />
      <StickyCTA />
      <TweaksPanel
        visible={tweaksOn}
        density={density} setDensity={(v) => { setDensity(v); persist({ density: v }); }}
        heroVariant={heroVariant} setHeroVariant={(v) => { setHeroVariant(v); persist({ heroVariant: v }); }}
        accentHue={accentHue} setAccentHue={(v) => { setAccentHue(v); persist({ accentHue: v }); }}
      />
    </LandingStatsProvider>
  );
}

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