const { useState, useEffect, useRef, useMemo, useCallback } = React;

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});
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return y;
}

function useParallax(speed=0.3){
  const ref = useRef(null);
  const [y, setY] = useState(0);
  useEffect(() => {
    let raf = 0;
    const onScroll = () => {
      if (raf) return;
      raf = requestAnimationFrame(() => {
        if (!ref.current) { raf=0; return; }
        const rect = ref.current.getBoundingClientRect();
        const vh = window.innerHeight;
        const progress = (rect.top + rect.height/2 - vh/2) / vh;
        setY(-progress * speed * 100);
        raf = 0;
      });
    };
    window.addEventListener('scroll', onScroll, {passive:true});
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, [speed]);
  return [ref, y];
}

// Returns element's scroll progress [-1, 1] — -1 when just entered bottom, 0 centered, 1 about to exit top
function useScrollProgress(){
  const ref = useRef(null);
  const [p, setP] = useState(-1);
  useEffect(() => {
    let raf = 0;
    const onScroll = () => {
      if (raf) return;
      raf = requestAnimationFrame(() => {
        if (!ref.current) { raf=0; return; }
        const rect = ref.current.getBoundingClientRect();
        const vh = window.innerHeight;
        const mid = rect.top + rect.height/2;
        const prog = (vh/2 - mid) / ((rect.height + vh)/2);
        setP(Math.max(-1.2, Math.min(1.2, prog)));
        raf = 0;
      });
    };
    window.addEventListener('scroll', onScroll, {passive:true});
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return [ref, p];
}

function useInView(opts={threshold:0.15}){
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    if (!ref.current) return;
    const io = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) { setInView(true); io.disconnect(); }
    }, opts);
    io.observe(ref.current);
    return () => io.disconnect();
  }, []);
  return [ref, inView];
}

function useCountdown(target){
  const [, setTick] = useState(0);
  useEffect(() => {
    const i = setInterval(() => setTick(t => t+1), 1000);
    return () => clearInterval(i);
  }, []);
  const diff = Math.max(0, target - Date.now());
  return {
    days: Math.floor(diff / 86400000),
    hours: Math.floor((diff / 3600000) % 24),
    minutes: Math.floor((diff / 60000) % 60),
    seconds: Math.floor((diff/1000) % 60),
    total: diff,
  };
}

function useMouseParallax(factor=0.02){
  const [p, setP] = useState({x:0,y:0});
  useEffect(() => {
    // Su touch non c'è mousemove — saltiamo il listener
    if (window.matchMedia('(hover: none)').matches) return;
    const onMove = (e) => {
      setP({
        x: (e.clientX / window.innerWidth - 0.5) * factor * 100,
        y: (e.clientY / window.innerHeight - 0.5) * factor * 100,
      });
    };
    window.addEventListener('mousemove', onMove);
    return () => window.removeEventListener('mousemove', onMove);
  }, [factor]);
  return p;
}

// Ritorna true se la viewport è sotto il breakpoint (default 768px)
function useIsMobile(breakpoint=768){
  const [mobile, setMobile] = useState(() => window.innerWidth < breakpoint);
  useEffect(() => {
    const mq = window.matchMedia(`(max-width: ${breakpoint - 1}px)`);
    const handler = (e) => setMobile(e.matches);
    mq.addEventListener('change', handler);
    return () => mq.removeEventListener('change', handler);
  }, [breakpoint]);
  return mobile;
}

Object.assign(window, { useScrollY, useParallax, useScrollProgress, useInView, useCountdown, useMouseParallax, useIsMobile });
