// Global chrome extras: scroll progress, custom cursor, sticky section nav,
// cursor-tracked hero glow, and an auto-play-on-first-view hook for
// signature interactions.

const { useState: useStateCX, useEffect: useEffectCX, useRef: useRefCX, useCallback: useCallbackCX } = React;

/* ----------------- Scroll progress bar ----------------- */
window.ScrollProgress = function ScrollProgress() {
  const [p, setP] = useStateCX(0);
  useEffectCX(() => {
    const onScroll = () => {
      const doc = document.documentElement;
      const max = doc.scrollHeight - window.innerHeight;
      const pct = max <= 0 ? 0 : Math.min(1, Math.max(0, window.scrollY / max));
      setP(pct);
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    return () => {
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
    };
  }, []);
  return (
    <div className="scroll-progress" aria-hidden="true">
      <div className="scroll-progress-fill" style={{ transform: `scaleX(${p})` }} />
    </div>
  );
};

/* ----------------- Sticky section mini-nav -----------------
   Looks for elements with [data-section-nav] and uses their
   data-section-nav value as the label. Active section is whatever
   section's top is above the viewport midpoint. Appears once the
   hero has scrolled past; tucks away on scroll-down, re-appears
   on scroll-up. */
window.SectionNav = function SectionNav() {
  const [items, setItems] = useStateCX([]);
  const [active, setActive] = useStateCX(0);
  const [visible, setVisible] = useStateCX(false);   // shown at all (past hero)
  const [hidden, setHidden] = useStateCX(false);     // tucked away on scroll-down
  const lastY = useRefCX(0);

  // Collect sections on mount + on resize.
  useEffectCX(() => {
    const gather = () => {
      const els = Array.from(document.querySelectorAll('[data-section-nav]'));
      setItems(els.map(el => ({ label: el.getAttribute('data-section-nav'), el })));
    };
    gather();
    window.addEventListener('resize', gather);
    // Re-gather after reveal observers likely finish.
    const t = setTimeout(gather, 300);
    return () => { window.removeEventListener('resize', gather); clearTimeout(t); };
  }, []);

  useEffectCX(() => {
    const onScroll = () => {
      const y = window.scrollY;
      const hero = document.querySelector('.hero, .page-hero');
      const threshold = hero ? hero.offsetTop + hero.offsetHeight * 0.55 : 400;
      const pastHero = y > threshold;
      setVisible(pastHero);

      // Scroll-direction tuck.
      const delta = y - lastY.current;
      if (pastHero) {
        if (delta > 6) setHidden(true);
        else if (delta < -4) setHidden(false);
      } else {
        setHidden(false);
      }
      lastY.current = y;

      // Active section: last one whose top is above viewport midline.
      const mid = y + window.innerHeight * 0.35;
      let a = 0;
      items.forEach((it, i) => {
        if (!it.el) return;
        const top = it.el.getBoundingClientRect().top + y;
        if (top <= mid) a = i;
      });
      setActive(a);
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, [items]);

  if (!items.length) return null;

  const jump = (i) => {
    const el = items[i]?.el;
    if (!el) return;
    const y = el.getBoundingClientRect().top + window.scrollY - 88;
    window.scrollTo({ top: y, behavior: 'smooth' });
  };

  return (
    <div
      className={`section-nav ${visible ? 'section-nav-visible' : ''} ${hidden ? 'section-nav-hidden' : ''}`}
      aria-label="Section navigation"
    >
      <div className="section-nav-inner">
        {items.map((it, i) => (
          <button
            key={it.label + i}
            className={`section-nav-item ${i === active ? 'active' : ''}`}
            onClick={() => jump(i)}
          >
            <span className="section-nav-dot" />
            <span className="section-nav-label">{it.label}</span>
          </button>
        ))}
      </div>
    </div>
  );
};

/* ----------------- Custom cursor -----------------
   Two layered dots — a precise 6px inner pip that tracks the pointer 1:1,
   and a 28px outer ring that lags slightly and expands on interactive
   elements. Auto-disables on touch devices and when the user has
   `prefers-reduced-motion: reduce`. Does NOT hide the native cursor
   globally so hit-target precision stays intact; we only mark the
   document with `data-cc="on"` so CSS can hide it where appropriate. */
window.CustomCursor = function CustomCursor() {
  const ringRef = useRefCX(null);
  const dotRef  = useRefCX(null);

  useEffectCX(() => {
    // Bail on touch / reduced motion — native cursor is the right call there.
    const isTouch  = window.matchMedia('(pointer: coarse)').matches;
    const reduced  = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    if (isTouch || reduced) return;

    document.documentElement.setAttribute('data-cc', 'on');

    // Target positions (mouse) and rendered positions (eased) for the ring.
    const target = { x: -100, y: -100 };
    const ring   = { x: -100, y: -100 };
    let raf = 0;
    let hoverInteractive = false;
    let down = false;
    let running = true;

    const tick = () => {
      if (!running) return;
      // Dot snaps to mouse — zero lag so clicks feel precise.
      if (dotRef.current) {
        dotRef.current.style.transform = `translate3d(${target.x}px, ${target.y}px, 0) translate(-50%, -50%)`;
      }
      // Ring eases toward mouse — subtle lag = the "tech" feel.
      ring.x += (target.x - ring.x) * 0.22;
      ring.y += (target.y - ring.y) * 0.22;
      if (ringRef.current) {
        ringRef.current.style.transform = `translate3d(${ring.x}px, ${ring.y}px, 0) translate(-50%, -50%)`;
      }
      raf = requestAnimationFrame(tick);
    };

    const onMove = (e) => {
      target.x = e.clientX;
      target.y = e.clientY;
      // Lazy hover detection: only inspect the target element on move,
      // no per-element listener plumbing to maintain.
      const t = e.target;
      const interactive = !!(t && (t.closest && t.closest('a, button, [role="button"], input, select, textarea, label, summary, .clickable, [data-cc-hover]')));
      if (interactive !== hoverInteractive) {
        hoverInteractive = interactive;
        ringRef.current?.classList.toggle('cc-ring-hover', interactive);
        dotRef.current?.classList.toggle('cc-dot-hover', interactive);
      }
    };

    const onDown = () => {
      down = true;
      ringRef.current?.classList.add('cc-ring-down');
    };
    const onUp = () => {
      down = false;
      ringRef.current?.classList.remove('cc-ring-down');
    };
    const onLeave = () => {
      ringRef.current?.classList.add('cc-ring-hidden');
      dotRef.current?.classList.add('cc-dot-hidden');
    };
    const onEnter = () => {
      ringRef.current?.classList.remove('cc-ring-hidden');
      dotRef.current?.classList.remove('cc-dot-hidden');
    };

    window.addEventListener('mousemove', onMove, { passive: true });
    window.addEventListener('mousedown', onDown, { passive: true });
    window.addEventListener('mouseup', onUp, { passive: true });
    document.addEventListener('mouseleave', onLeave);
    document.addEventListener('mouseenter', onEnter);
    raf = requestAnimationFrame(tick);

    return () => {
      running = false;
      cancelAnimationFrame(raf);
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mousedown', onDown);
      window.removeEventListener('mouseup', onUp);
      document.removeEventListener('mouseleave', onLeave);
      document.removeEventListener('mouseenter', onEnter);
      document.documentElement.removeAttribute('data-cc');
    };
  }, []);

  return (
    <>
      <div ref={ringRef} className="cc-ring cc-ring-hidden" aria-hidden="true" />
      <div ref={dotRef} className="cc-dot cc-dot-hidden" aria-hidden="true" />
    </>
  );
};

/* ----------------- Hero ambient glow (static, no cursor tracking) ----------------- */
window.useHeroGlow = function useHeroGlow() {
  // Intentionally a no-op. The glow is pure CSS (.hero-bg-glow),
  // no mouse tracking — looks nicer and doesn't leave edge artifacts.
};

/* ----------------- Auto-play on first in-view -----------------
   useAutoPlayOnView(ref, onPlay) — calls onPlay once, then hands off. */
window.useAutoPlayOnView = function useAutoPlayOnView(ref, onPlay, opts = {}) {
  const played = useRefCX(false);
  useEffectCX(() => {
    if (!ref.current || played.current) return;
    if (!('IntersectionObserver' in window)) {
      // Fallback — just run on mount.
      played.current = true;
      setTimeout(() => onPlay && onPlay(), 300);
      return;
    }
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting && !played.current) {
          played.current = true;
          io.disconnect();
          onPlay && onPlay();
        }
      });
    }, { threshold: opts.threshold ?? 0.35, rootMargin: opts.rootMargin ?? '0px 0px -10% 0px' });
    io.observe(ref.current);
    return () => io.disconnect();
  }, [ref]);
};
