// PHAROS — shared reveal-on-scroll
// Single global IntersectionObserver shared across all Reveal nodes.
// Replaces the previous per-component observer + setTimeout fallback.
const { useState, useEffect, useRef, useCallback } = React;

const REVEAL_MARGIN = "0px 0px -40px 0px";
const REVEAL_THRESHOLD = 0.08;

let _sharedObserver = null;
const _callbacks = new WeakMap();

function getSharedObserver() {
  if (_sharedObserver) return _sharedObserver;
  if (typeof IntersectionObserver === "undefined") return null;
  _sharedObserver = new IntersectionObserver((entries, obs) => {
    for (const entry of entries) {
      if (!entry.isIntersecting) continue;
      const cb = _callbacks.get(entry.target);
      if (cb) cb();
      obs.unobserve(entry.target);
      _callbacks.delete(entry.target);
    }
  }, { threshold: REVEAL_THRESHOLD, rootMargin: REVEAL_MARGIN });
  return _sharedObserver;
}

function useReveal() {
  const ref = useRef(null);
  const [seen, setSeen] = useState(false);

  useEffect(() => {
    const el = ref.current;
    if (!el || seen) return;

    // Already on screen — flip on next frame, no observer needed.
    const rect = el.getBoundingClientRect();
    const vh = window.innerHeight || document.documentElement.clientHeight;
    if (rect.top < vh * 0.95 && rect.bottom > 0) {
      const id = requestAnimationFrame(() => setSeen(true));
      return () => cancelAnimationFrame(id);
    }

    const obs = getSharedObserver();
    if (!obs) { setSeen(true); return; } // no IO support → reveal immediately

    _callbacks.set(el, () => setSeen(true));
    obs.observe(el);
    return () => {
      obs.unobserve(el);
      _callbacks.delete(el);
    };
  }, [seen]);

  return [ref, seen];
}

function Reveal({ children, delay = 0, as: Tag = "div", className = "", style, ...rest }) {
  const [ref, seen] = useReveal();
  const merged = { transitionDelay: `${delay}ms`, ...(style || {}) };
  return (
    <Tag
      ref={ref}
      className={`reveal ${seen ? "is-in" : ""} ${className}`.trim()}
      style={merged}
      {...rest}
    >{children}</Tag>
  );
}

window.useReveal = useReveal;
window.Reveal = Reveal;
