/* Reusable UI helpers — reveal, magnetic, parallax, counter */

function useReveal(opts = {}) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    const io = new IntersectionObserver((ents) => {
      ents.forEach(e => { if (e.isIntersecting) { el.classList.add('in'); io.unobserve(el); } });
    }, { threshold: opts.threshold ?? 0.15, rootMargin: opts.rootMargin ?? '0px 0px -8% 0px' });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return ref;
}

function Reveal({ children, className = '', delay = 0, as: As = 'div', style = {}, scale = false, ...rest }) {
  const ref = useReveal();
  const base = scale ? 'reveal-scale' : 'reveal';
  return (
    <As ref={ref} className={`${base} ${className}`} style={{ transitionDelay: `${delay}ms`, ...style }} {...rest}>
      {children}
    </As>
  );
}

function useNavShrink() {
  React.useEffect(() => {
    const nav = document.querySelector('.nav');
    if (!nav) return;
    const onScroll = () => {
      if (window.scrollY > 30) nav.classList.add('scrolled');
      else nav.classList.remove('scrolled');
    };
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
}

/* Scroll-driven parallax — translates element on Y as it passes through viewport */
function useScrollParallax(strength = 30) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    let raf = 0;
    const tick = () => {
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight;
      const progress = (vh / 2 - (r.top + r.height / 2)) / vh;
      el.style.transform = `translate3d(0, ${(progress * strength).toFixed(1)}px, 0)`;
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [strength]);
  return ref;
}

/* Mouse-tracked parallax — translates inside container (or window) based on cursor */
function useMouseParallax(strength = 20, container = null) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    let raf = 0, tx = 0, ty = 0, cx = 0, cy = 0;
    const target = container ? container.current ?? document : window;
    const onMove = (e) => {
      const w = window.innerWidth, h = window.innerHeight;
      tx = ((e.clientX / w) - 0.5) * strength;
      ty = ((e.clientY / h) - 0.5) * strength;
    };
    const tick = () => {
      cx += (tx - cx) * 0.08; cy += (ty - cy) * 0.08;
      el.style.transform = `translate3d(${cx.toFixed(2)}px, ${cy.toFixed(2)}px, 0)`;
      raf = requestAnimationFrame(tick);
    };
    target.addEventListener('mousemove', onMove);
    raf = requestAnimationFrame(tick);
    return () => { cancelAnimationFrame(raf); target.removeEventListener('mousemove', onMove); };
  }, [strength]);
  return ref;
}

/* Tilt: rotate based on cursor position within element */
function useTilt(max = 8) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    let raf = 0; let tx = 0, ty = 0, cx = 0, cy = 0;
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      const px = (e.clientX - r.left) / r.width - 0.5;
      const py = (e.clientY - r.top) / r.height - 0.5;
      tx = -py * max; ty = px * max;
    };
    const onLeave = () => { tx = 0; ty = 0; };
    const tick = () => {
      cx += (tx - cx) * 0.12; cy += (ty - cy) * 0.12;
      el.style.transform = `perspective(1400px) rotateX(${cx.toFixed(2)}deg) rotateY(${cy.toFixed(2)}deg)`;
      raf = requestAnimationFrame(tick);
    };
    el.addEventListener('mousemove', onMove);
    el.addEventListener('mouseleave', onLeave);
    raf = requestAnimationFrame(tick);
    return () => { cancelAnimationFrame(raf); el.removeEventListener('mousemove', onMove); el.removeEventListener('mouseleave', onLeave); };
  }, [max]);
  return ref;
}

/* Magnetic button — inner translates toward cursor on hover */
function Magnetic({ children, strength = 0.4, className = '', as: As = 'button', ...rest }) {
  const outer = React.useRef(null);
  const inner = React.useRef(null);
  React.useEffect(() => {
    const el = outer.current; const inn = inner.current; if (!el || !inn) return;
    let raf = 0, tx = 0, ty = 0, cx = 0, cy = 0;
    const onMove = (e) => {
      const r = el.getBoundingClientRect();
      tx = (e.clientX - (r.left + r.width / 2)) * strength;
      ty = (e.clientY - (r.top + r.height / 2)) * strength;
    };
    const onLeave = () => { tx = 0; ty = 0; };
    const tick = () => {
      cx += (tx - cx) * 0.18; cy += (ty - cy) * 0.18;
      inn.style.transform = `translate(${cx.toFixed(2)}px, ${cy.toFixed(2)}px)`;
      raf = requestAnimationFrame(tick);
    };
    el.addEventListener('mousemove', onMove);
    el.addEventListener('mouseleave', onLeave);
    raf = requestAnimationFrame(tick);
    return () => { cancelAnimationFrame(raf); el.removeEventListener('mousemove', onMove); el.removeEventListener('mouseleave', onLeave); };
  }, [strength]);
  return (
    <As ref={outer} className={className} {...rest}>
      <span className="mag-inner" ref={inner} style={{ display:'inline-flex', alignItems:'center', gap:12 }}>{children}</span>
    </As>
  );
}

/* Animated counter — increments from 0 to target once visible */
function Counter({ to, suffix = '', duration = 1600, prefix = '' }) {
  const ref = React.useRef(null);
  const [val, setVal] = React.useState(0);
  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    let started = false;
    const io = new IntersectionObserver((ents) => {
      if (ents[0].isIntersecting && !started) {
        started = true;
        const start = performance.now();
        const tick = (t) => {
          const p = Math.min(1, (t - start) / duration);
          const eased = 1 - Math.pow(1 - p, 3);
          setVal(Math.round(eased * to));
          if (p < 1) requestAnimationFrame(tick);
        };
        requestAnimationFrame(tick);
        io.disconnect();
      }
    }, { threshold: 0.4 });
    io.observe(el);
    return () => io.disconnect();
  }, [to, duration]);
  return <span ref={ref}>{prefix}{val}{suffix}</span>;
}

/* Text reveal with per-letter stagger */
function SplitText({ text, delay = 0, className = '', stagger = 30 }) {
  const ref = useReveal({ threshold: 0.2 });
  return (
    <span ref={ref} className={`split-text ${className}`}>
      {text.split('').map((c, i) => (
        <span key={i} className="char" style={{ transitionDelay: `${delay + i * stagger}ms` }}>{c === ' ' ? ' ' : c}</span>
      ))}
    </span>
  );
}

Object.assign(window, { Reveal, useReveal, useNavShrink, useParallax: useScrollParallax, useScrollParallax, useMouseParallax, useTilt, Magnetic, Counter, SplitText });
