// hooks.jsx — shared utilities
const { useState, useEffect, useRef, useMemo, useCallback } = React;

// IntersectionObserver-based reveal hook
function useReveal() {
  useEffect(() => {
    const els = document.querySelectorAll('.reveal');
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) {
          e.target.classList.add('in');
          io.unobserve(e.target);
        }
      });
    }, { threshold: 0.12, rootMargin: '0px 0px -8% 0px' });
    els.forEach(el => io.observe(el));
    return () => io.disconnect();
  }, []);
}

// Scroll progress 0..1
function useScrollY() {
  const [y, setY] = useState(0);
  useEffect(() => {
    let raf = 0;
    const onScroll = () => {
      if (raf) return;
      raf = requestAnimationFrame(() => {
        setY(window.scrollY);
        raf = 0;
      });
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return y;
}

// Live clock (UTC−3, Uruguay)
function useClock() {
  const [t, setT] = useState(() => new Date());
  useEffect(() => {
    const id = setInterval(() => setT(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  return t;
}

function fmtTime(d) {
  // UY local string
  return d.toLocaleTimeString('en-US', { hour12: false, timeZone: 'America/Montevideo' });
}

// Mouse position normalized 0..1 over window
function useMouse() {
  const ref = useRef({ x: 0.5, y: 0.5 });
  useEffect(() => {
    const onMove = (e) => {
      ref.current.x = e.clientX / window.innerWidth;
      ref.current.y = e.clientY / window.innerHeight;
    };
    window.addEventListener('mousemove', onMove, { passive: true });
    return () => window.removeEventListener('mousemove', onMove);
  }, []);
  return ref;
}

Object.assign(window, { useReveal, useScrollY, useClock, fmtTime, useMouse });
