// hooks.jsx — reveal + counter hooks, magnetic wrapper
const { useEffect: useEffectH, useRef: useRefH, useState: useStateH } = React;

function useReveal() {
  const ref = useRefH(null);
  useEffectH(() => {
    const el = ref.current;
    if (!el) return;
    // Immediate check on mount: if already in view, show right away.
    // This catches above-the-fold elements on initial page load where IO
    // can miss the first intersection.
    const check = () => {
      if (!el.isConnected) return;
      const r = el.getBoundingClientRect();
      if (r.top < window.innerHeight * 0.95 && r.bottom > 0) {
        el.classList.add('in');
        return true;
      }
      return false;
    };
    if (check()) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) {
          el.classList.add('in');
          io.unobserve(el);
        }
      });
    }, { threshold: 0.15 });
    io.observe(el);
    // Also re-check on next paint in case layout shifts bring it into view
    const raf = requestAnimationFrame(() => { if (check()) io.disconnect(); });
    return () => { io.disconnect(); cancelAnimationFrame(raf); };
  }, []);
  return ref;
}

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

function Counter({ to, suffix = '', duration = 1800, decimals = 0, prefix = '' }) {
  const [val, setVal] = useStateH(0);
  const ref = useRefH(null);
  const startedRef = useRefH(false);

  useEffectH(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting && !startedRef.current) {
          startedRef.current = 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(to * eased);
            if (p < 1) requestAnimationFrame(tick);
          };
          requestAnimationFrame(tick);
          io.disconnect();
        }
      });
    }, { threshold: 0.3 });
    io.observe(el);
    return () => io.disconnect();
  }, [to, duration]);

  const formatted = decimals > 0 ? val.toFixed(decimals) : Math.floor(val).toLocaleString();
  return <span ref={ref}>{prefix}{formatted}{suffix}</span>;
}

function Magnetic({ children, strength = 0.25, style, ...rest }) {
  const ref = useRefH(null);
  const [pos, setPos] = useStateH({ x: 0, y: 0 });
  const onMove = (e) => {
    const r = ref.current.getBoundingClientRect();
    const x = (e.clientX - r.left - r.width / 2) * strength;
    const y = (e.clientY - r.top - r.height / 2) * strength;
    setPos({ x, y });
  };
  const onLeave = () => setPos({ x: 0, y: 0 });
  return (
    <div ref={ref} onMouseMove={onMove} onMouseLeave={onLeave}
      style={{
        transform: `translate(${pos.x}px, ${pos.y}px)`,
        transition: 'transform 0.3s cubic-bezier(.2,.8,.2,1)',
        ...style
      }} {...rest}>
      {children}
    </div>
  );
}

// Spotlight on hover — wraps a card
function Spotlight({ children, style, color = '139, 233, 253', ...rest }) {
  const ref = useRefH(null);
  const [pos, setPos] = useStateH({ x: -999, y: -999, on: false });
  const onMove = (e) => {
    const r = ref.current.getBoundingClientRect();
    setPos({ x: e.clientX - r.left, y: e.clientY - r.top, on: true });
  };
  const onLeave = () => setPos({ x: -999, y: -999, on: false });
  return (
    <div ref={ref} onMouseMove={onMove} onMouseLeave={onLeave}
      style={{ position: 'relative', ...style }} {...rest}>
      <div style={{
        position: 'absolute', inset: 0, pointerEvents: 'none',
        background: `radial-gradient(320px circle at ${pos.x}px ${pos.y}px, rgba(${color}, 0.12), transparent 60%)`,
        opacity: pos.on ? 1 : 0,
        transition: 'opacity 0.3s',
        borderRadius: 'inherit',
      }}/>
      {children}
    </div>
  );
}

window.Reveal = Reveal;
window.Counter = Counter;
window.Magnetic = Magnetic;
window.Spotlight = Spotlight;

function useIsMobile(breakpoint = 640) {
  const [isMobile, setIsMobile] = useStateH(() =>
    typeof window !== 'undefined' ? window.innerWidth < breakpoint : false
  );
  useEffectH(() => {
    const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);
    const handler = (e) => setIsMobile(e.matches);
    if (mq.addEventListener) mq.addEventListener('change', handler);
    else mq.addListener(handler);
    return () => {
      if (mq.removeEventListener) mq.removeEventListener('change', handler);
      else mq.removeListener(handler);
    };
  }, [breakpoint]);
  return isMobile;
}

window.useIsMobile = useIsMobile;
