/* global React */

/* Hook: reveal on scroll */
function useReveal() {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    // immediate check: if already in viewport, reveal now (skip transition)
    const r = el.getBoundingClientRect();
    if (r.top < window.innerHeight && r.bottom > 0) {
      el.style.transition = "none";
      el.classList.add("in");
      // force reflow then restore transition
      void el.offsetWidth;
      requestAnimationFrame(() => {
        el.style.transition = "";
      });
      return;
    }
    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 -60px 0px" }
    );
    io.observe(el);
    // fallback: ensure visible within 800ms even if IO fails
    const fallback = setTimeout(() => {
      if (el && !el.classList.contains("in")) el.classList.add("in");
    }, 800);
    return () => { io.disconnect(); clearTimeout(fallback); };
  }, []);
  return ref;
}

function Reveal({ as: Tag = "div", className = "", delay, scale, stagger, children, ...rest }) {
  const ref = useReveal();
  const cls = [
    scale ? "reveal-scale" : (stagger ? "reveal-stagger" : "reveal"),
    delay ? `delay-${delay}` : "",
    className,
  ].filter(Boolean).join(" ");
  return <Tag ref={ref} className={cls} {...rest}>{children}</Tag>;
}

/* Number counter on enter */
function CountUp({ to, prefix = "", suffix = "", duration = 1400, decimals = 0 }) {
  const ref = React.useRef(null);
  const [val, setVal] = React.useState(0);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          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.unobserve(e.target);
        }
      });
    }, { threshold: 0.4 });
    io.observe(el);
    return () => io.disconnect();
  }, [to, duration]);
  const formatted = decimals > 0
    ? val.toFixed(decimals).replace(".", ",")
    : Math.round(val).toLocaleString("pt-BR");
  return <span ref={ref} className="count-up">{prefix}{formatted}{suffix}</span>;
}

/* Parallax orb */
function ParallaxOrb({ kind = "blue", style }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const onScroll = () => {
      const r = el.getBoundingClientRect();
      const center = r.top + r.height / 2;
      const dist = (window.innerHeight / 2) - center;
      el.style.transform = `translate3d(0, ${dist * 0.15}px, 0)`;
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  return <div ref={ref} className={`bg-orb bg-orb-${kind}`} style={style} />;
}

window.LegadoMotion = { useReveal, Reveal, CountUp, ParallaxOrb };
Object.assign(window, { useReveal, Reveal, CountUp, ParallaxOrb });
