/* =========================================================
   Scroll & parallax hooks + components
   ========================================================= */

// -------- low-level scroll progress for a specific element --------
function useElementScroll(ref, opts = {}) {
  // returns 0 when element bottom enters viewport, 1 when its top leaves
  const [t, setT] = React.useState(0);
  React.useEffect(() => {
    const onScroll = () => {
      const el = ref.current; if (!el) return;
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight;
      // 0 when r.top === vh (just entered), 1 when r.bottom === 0 (left)
      const span = vh + r.height;
      const travelled = vh - r.top;
      setT(Math.max(0, Math.min(1, travelled / span)));
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
    };
  }, [ref]);
  return t;
}

// -------- intersection observer reveal --------
function useReveal(opts = { threshold: 0.18 }) {
  const ref = React.useRef(null);
  const [shown, setShown] = React.useState(false);
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver(
      ([e]) => { if (e.isIntersecting) { setShown(true); io.disconnect(); } },
      { threshold: opts.threshold || 0.18 }
    );
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return [ref, shown];
}

// Reveal wrapper — fades + translates children when they scroll into view
function Reveal({ children, delay = 0, y = 28, as: Tag = "div", className = "", style = {} }) {
  const [ref, shown] = useReveal();
  return (
    <Tag
      ref={ref}
      className={className + " r-reveal" + (shown ? " is-shown" : "")}
      style={{ ...style, transitionDelay: `${delay}ms`, "--reveal-y": `${y}px` }}
    >
      {children}
    </Tag>
  );
}

// Parallax wrapper — shifts an element on its own scroll progress
function Parallax({ children, speed = 30, className = "", style = {} }) {
  const ref = React.useRef(null);
  const t = useElementScroll(ref);
  // shift from +speed (entering) to -speed (leaving), with 0 in middle
  const y = (t - 0.5) * -speed * 2;
  return (
    <div ref={ref} className={className} style={{ ...style, transform: `translate3d(0, ${y}px, 0)`, willChange: "transform" }}>
      {children}
    </div>
  );
}

// 3D tilt — mouse-tracked
function Tilt({ children, max = 8, scale = 1.015, className = "", style = {} }) {
  const ref = React.useRef(null);
  const [tr, setTr] = React.useState("perspective(900px) rotateX(0deg) rotateY(0deg) scale(1)");
  const onMove = (e) => {
    const el = ref.current; if (!el) return;
    const r = el.getBoundingClientRect();
    const px = (e.clientX - r.left) / r.width;   // 0..1
    const py = (e.clientY - r.top) / r.height;   // 0..1
    const ry = (px - 0.5) * 2 * max;
    const rx = (0.5 - py) * 2 * max;
    setTr(`perspective(900px) rotateX(${rx}deg) rotateY(${ry}deg) scale(${scale})`);
  };
  const onLeave = () => setTr("perspective(900px) rotateX(0deg) rotateY(0deg) scale(1)");
  return (
    <div
      ref={ref}
      className={"r-tilt " + className}
      style={{ ...style, transform: tr, transition: "transform 300ms cubic-bezier(.2,.7,.2,1)", transformStyle: "preserve-3d" }}
      onMouseMove={onMove}
      onMouseLeave={onLeave}
    >
      {children}
    </div>
  );
}

// Magnetic button — slight pull toward cursor
function Magnetic({ children, strength = 12, className = "", style = {}, ...rest }) {
  const ref = React.useRef(null);
  const [tr, setTr] = React.useState("translate3d(0,0,0)");
  const onMove = (e) => {
    const el = ref.current; if (!el) return;
    const r = el.getBoundingClientRect();
    const x = (e.clientX - (r.left + r.width / 2)) / (r.width / 2);
    const y = (e.clientY - (r.top + r.height / 2)) / (r.height / 2);
    setTr(`translate3d(${x * strength}px, ${y * strength}px, 0)`);
  };
  const onLeave = () => setTr("translate3d(0,0,0)");
  return (
    <span
      ref={ref}
      className={className}
      style={{ ...style, display: "inline-block", transform: tr, transition: "transform 250ms cubic-bezier(.2,.7,.2,1)" }}
      onMouseMove={onMove}
      onMouseLeave={onLeave}
      {...rest}
    >
      {children}
    </span>
  );
}

Object.assign(window, { Reveal, Parallax, Tilt, Magnetic, useElementScroll, useReveal });
