// Animation helpers: reveal on scroll, count-up, scroll progress, magnetic CTA

// Reveal-on-view: use IntersectionObserver once
const useReveal = () => {
  const ref = React.useRef(null);
  const [inView, setInView] = React.useState(false);
  React.useEffect(() => {
    if (!ref.current) return;
    const el = ref.current;
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) { setInView(true); io.disconnect(); }
      });
    }, { threshold: 0.15, rootMargin: "0px 0px -50px 0px" });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return [ref, inView];
};

const Reveal = ({ children, as:Tag="div", className="", stagger=false, ...rest }) => {
  const [ref, v] = useReveal();
  return (
    <Tag ref={ref} className={`${stagger?"reveal-stagger":"reveal"} ${v?"in":""} ${className}`} {...rest}>
      {children}
    </Tag>
  );
};

// Count-up hook
const useCountUp = (target, { decimals=0, duration=1200, trigger=true } = {}) => {
  const [val, setVal] = React.useState(0);
  React.useEffect(() => {
    if (!trigger) return;
    let raf, start;
    const from = 0;
    const to = Number(target) || 0;
    const ease = (t) => 1 - Math.pow(1 - t, 3);
    const step = (ts) => {
      if (!start) start = ts;
      const p = Math.min(1, (ts - start) / duration);
      setVal(from + (to - from) * ease(p));
      if (p < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [target, duration, trigger]);
  return Number(val.toFixed(decimals));
};

const CountUp = ({ value, decimals=0, format, trigger=true, suffix="", prefix="" }) => {
  const v = useCountUp(value, { decimals, trigger });
  const out = format ? format(v) : v.toLocaleString("ru-RU", { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
  return <span className="tabular">{prefix}{out}{suffix}</span>;
};

// Wrap a whole section in a viewport-triggered container; children use `trigger` prop from context
const CountSection = ({ children, className="" }) => {
  const [ref, v] = useReveal();
  return <div ref={ref} className={className} data-in={v?"1":"0"}>{typeof children === "function" ? children(v) : children}</div>;
};

// Scroll progress bar
const ScrollProgress = () => {
  React.useEffect(() => {
    let raf = 0;
    const compute = () => {
      raf = 0;
      const docEl = document.documentElement;
      const scrollTop = window.scrollY != null ? window.scrollY : docEl.scrollTop || document.body.scrollTop || 0;
      const viewport = window.innerHeight || docEl.clientHeight;
      const fullHeight = Math.max(docEl.scrollHeight, document.body ? document.body.scrollHeight : 0);
      const max = fullHeight - viewport;
      const p = max > 0 ? Math.min(100, Math.max(0, (scrollTop / max) * 100)) : 0;
      const bar = document.getElementById("scroll-prog");
      if (bar) bar.style.setProperty("--p", p + "%");
    };
    const onScroll = () => {
      if (raf) return;
      raf = window.requestAnimationFrame(compute);
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    compute();
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      if (raf) cancelAnimationFrame(raf);
    };
  }, []);
  return <div id="scroll-prog" aria-hidden="true" />;
};

// Magnetic glow wrapper for CTA buttons
const MagneticCTA = ({ children }) => {
  const ref = React.useRef(null);
  const onMove = (e) => {
    const el = ref.current; if (!el) return;
    const r = el.getBoundingClientRect();
    el.style.setProperty("--mx", (e.clientX - r.left) + "px");
    el.style.setProperty("--my", (e.clientY - r.top) + "px");
  };
  return (
    <span ref={ref} onMouseMove={onMove} className="cta-glow inline-flex rounded-md">
      {children}
    </span>
  );
};

Object.assign(window, { useReveal, Reveal, useCountUp, CountUp, CountSection, ScrollProgress, MagneticCTA });
