/* ScrollReveal.jsx
   Wrapper reutilizável: revela os filhos suavemente quando entram na viewport.
   Usa IntersectionObserver (sem lib, sem custo por frame).
   Props: delay (ms), as (tag), e quaisquer props extras repassadas ao elemento.
   prefers-reduced-motion: mostra imediatamente (a classe .reveal já trata isso no CSS). */
function ScrollReveal({ children, delay = 0, as = "div", className = "", style = {}, ...rest }) {
  const ref = React.useRef(null);
  const [shown, setShown] = React.useState(false);
  const [instant, setInstant] = React.useState(false); // revela sem transição (tab oculta / reduced)

  React.useLayoutEffect(() => {
    const el = ref.current;
    if (!el) return;

    // Se a timeline de animação não vai rodar (aba oculta) ou o usuário
    // pediu menos movimento, revela imediatamente, sem transição — evita
    // ficar preso em opacity:0 quando o navegador congela as transições.
    const reduced = window.matchMedia &&
      window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (document.visibilityState === "hidden" || reduced) {
      setInstant(true); setShown(true); return;
    }

    let done = false;
    const reveal = () => { if (!done) { done = true; setShown(true); cleanup(); } };

    let ticking = false;
    const check = () => {
      ticking = false;
      if (done || !el) return;
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight || document.documentElement.clientHeight;
      if (r.top < vh * 0.9 && r.bottom > 0) reveal();
    };
    const onScroll = () => { if (!ticking) { ticking = true; requestAnimationFrame(check); } };

    let io;
    if ("IntersectionObserver" in window) {
      io = new IntersectionObserver((entries) => {
        entries.forEach((e) => { if (e.isIntersecting) reveal(); });
      }, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" });
      io.observe(el);
    }
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll, { passive: true });
    // se a aba ficar visível depois, garante a checagem
    document.addEventListener("visibilitychange", check);
    check();

    function cleanup() {
      if (io) io.disconnect();
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      document.removeEventListener("visibilitychange", check);
    }
    return cleanup;
  }, []);

  const Tag = as;
  return (
    <Tag
      ref={ref}
      className={`reveal ${shown ? "in" : ""} ${className}`}
      style={{
        transitionDelay: shown ? `${delay}ms` : "0ms",
        ...(instant ? { transition: "none" } : null),
        ...style,
      }}
      {...rest}
    >
      {children}
    </Tag>
  );
}

Object.assign(window, { ScrollReveal });
