// flippy-effects.jsx — next-level scroll & interaction effects
// Cursor light, mouse parallax, scroll progress, letter-stagger reveal

// =====================================================================
// CursorLight — soft radial light that tracks the pointer
// Lazy + throttled via rAF
// =====================================================================
const CursorLight = () => {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    // disable on touch
    if (window.matchMedia("(pointer: coarse)").matches) return;
    let frame = null;
    let tx = window.innerWidth / 2;
    let ty = window.innerHeight / 2;
    const onMove = (e) => {
      tx = e.clientX;
      ty = e.clientY;
      if (!frame) {
        frame = requestAnimationFrame(() => {
          el.style.transform = `translate3d(${tx - 280}px, ${ty - 280}px, 0)`;
          frame = null;
        });
      }
    };
    window.addEventListener("pointermove", onMove, { passive: true });
    return () => {
      window.removeEventListener("pointermove", onMove);
      if (frame) cancelAnimationFrame(frame);
    };
  }, []);
  return <div ref={ref} className="cursor-light" aria-hidden="true" />;
};

// =====================================================================
// ScrollProgress — thin acid bar at the very top of the viewport
// =====================================================================
const ScrollProgress = () => {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let frame = null;
    const onScroll = () => {
      if (frame) return;
      frame = requestAnimationFrame(() => {
        const h = document.documentElement.scrollHeight - window.innerHeight;
        const p = h <= 0 ? 0 : window.scrollY / h;
        el.style.transform = `scaleX(${p})`;
        frame = null;
      });
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  return <div ref={ref} className="scroll-progress" aria-hidden="true" />;
};

// =====================================================================
// MouseParallax — passes mouse-relative offset down via CSS var
//   <MouseParallax intensity={20}><div style={{transform: 'translate3d(var(--px,0), var(--py,0), 0)'}} /></MouseParallax>
// =====================================================================
const MouseParallax = ({ children, intensity = 20, className = "" }) => {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (window.matchMedia("(pointer: coarse)").matches) return;
    let frame = null;
    const onMove = (e) => {
      const rect = el.getBoundingClientRect();
      const cx = rect.left + rect.width / 2;
      const cy = rect.top + rect.height / 2;
      const dx = (e.clientX - cx) / window.innerWidth;
      const dy = (e.clientY - cy) / window.innerHeight;
      if (!frame) {
        frame = requestAnimationFrame(() => {
          el.style.setProperty("--px", `${dx * intensity}px`);
          el.style.setProperty("--py", `${dy * intensity}px`);
          frame = null;
        });
      }
    };
    window.addEventListener("pointermove", onMove, { passive: true });
    return () => window.removeEventListener("pointermove", onMove);
  }, [intensity]);
  return (
    <div ref={ref} className={className} style={{ "--px": "0px", "--py": "0px" }}>
      {children}
    </div>
  );
};

// =====================================================================
// SplitTextReveal — splits a string into letters and reveals stagger
// =====================================================================
const SplitTextReveal = ({ text, delay = 0, stagger = 30, className = "", style }) => {
  const [ref, shown] = useReveal({ threshold: 0.2 });
  const letters = text.split("");
  return (
    <span ref={ref} className={`split ${className}`} style={style} aria-label={text}>
      {letters.map((c, i) => (
        <span
          key={i}
          className="split-letter"
          aria-hidden="true"
          style={{
            display: "inline-block",
            transform: shown ? "translate3d(0,0,0) rotate(0)" : "translate3d(0, 1.1em, 0) rotate(8deg)",
            opacity: shown ? 1 : 0,
            transition: `transform 720ms cubic-bezier(0.22,1,0.36,1) ${delay + i * stagger}ms, opacity 480ms ${delay + i * stagger}ms`,
            whiteSpace: c === " " ? "pre" : "normal",
          }}
        >
          {c}
        </span>
      ))}
    </span>
  );
};

// =====================================================================
// useScrollParallax — translateY based on scroll, attaches to a ref
// Pass speed (negative = slower than scroll, positive = faster)
// =====================================================================
function useScrollParallax(speed = -0.15) {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let frame = null;
    const onScroll = () => {
      if (frame) return;
      frame = requestAnimationFrame(() => {
        const rect = el.getBoundingClientRect();
        const center = rect.top + rect.height / 2 - window.innerHeight / 2;
        el.style.setProperty("--scroll-y", `${center * speed}px`);
        frame = null;
      });
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, [speed]);
  return ref;
}

Object.assign(window, {
  CursorLight, ScrollProgress, MouseParallax, SplitTextReveal, useScrollParallax,
});
