/* Shared primitives: Reveal, Counter, Logo mark, icons */

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

function Reveal({ children, delay = 0, as: As = "div", className = "", ...rest }) {
  const ref = useRef(null);
  const [seen, setSeen] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;

    // Immediate check: if already in viewport at mount, reveal right away.
    const inView = () => {
      const r = el.getBoundingClientRect();
      const vh = window.innerHeight || document.documentElement.clientHeight;
      return r.top < vh * 0.95 && r.bottom > 0;
    };
    if (inView()) {
      // slight RAF to respect transition delays
      requestAnimationFrame(() => setSeen(true));
      return;
    }

    const io = new IntersectionObserver(
      ([e]) => { if (e.isIntersecting) { setSeen(true); io.disconnect(); } },
      { threshold: 0.05, rootMargin: "0px 0px -40px 0px" }
    );
    io.observe(el);

    // Fallback scroll listener in case IO misfires in iframe contexts
    const onScroll = () => { if (inView()) { setSeen(true); io.disconnect(); window.removeEventListener("scroll", onScroll); } };
    window.addEventListener("scroll", onScroll, { passive: true });

    // Safety net: if nothing has fired after 1.5s, reveal anyway
    const t = setTimeout(() => { setSeen(true); io.disconnect(); window.removeEventListener("scroll", onScroll); }, 1500);

    return () => { io.disconnect(); window.removeEventListener("scroll", onScroll); clearTimeout(t); };
  }, []);
  const d = delay ? `d${delay}` : "";
  return (
    <As ref={ref} className={`reveal ${d} ${seen ? "in" : ""} ${className}`} {...rest}>
      {children}
    </As>
  );
}

function Counter({ to, duration = 1600, suffix = "", prefix = "" }) {
  const ref = useRef(null);
  const [n, setN] = useState(0);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let started = false;
    const io = new IntersectionObserver(([e]) => {
      if (e.isIntersecting && !started) {
        started = true;
        const start = performance.now();
        const tick = (t) => {
          const p = Math.min(1, (t - start) / duration);
          const eased = 1 - Math.pow(1 - p, 3);
          setN(Math.floor(eased * to));
          if (p < 1) requestAnimationFrame(tick);
          else setN(to);
        };
        requestAnimationFrame(tick);
        io.disconnect();
      }
    }, { threshold: 0.35 });
    io.observe(el);
    return () => io.disconnect();
  }, [to, duration]);
  return <span ref={ref}>{prefix}{n.toLocaleString()}{suffix}</span>;
}

function LogoMark({ size = 22, spin = false }) {
  return (
    <svg width={size} height={size} viewBox="0 0 22 22" style={{ display: "block" }}>
      <g style={{
        transformOrigin: "11px 11px",
        animation: spin ? "logospin 14s linear infinite" : "none"
      }}>
        <circle cx="11" cy="11" r="9.5" fill="none" stroke="currentColor" strokeOpacity="0.35" strokeWidth="1"/>
        <line x1="11" y1="1.5" x2="11" y2="20.5" stroke="currentColor" strokeOpacity="0.55" strokeWidth="1"/>
        <line x1="1.5" y1="11" x2="20.5" y2="11" stroke="currentColor" strokeOpacity="0.2" strokeWidth="1"/>
        <circle cx="11" cy="11" r="2.4" fill="var(--accent)"/>
      </g>
      <style>{`@keyframes logospin { to { transform: rotate(360deg); } }`}</style>
    </svg>
  );
}

function Arrow({ size = 14 }) {
  return (
    <svg className="arrow" width={size} height={size} viewBox="0 0 14 14" fill="none" aria-hidden="true">
      <path d="M1 7h12m-5-5 5 5-5 5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  );
}

function LinkedInIcon({ size = 13 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" style={{ display: "block" }}>
      <path d="M20.45 20.45h-3.56v-5.57c0-1.33-.03-3.04-1.85-3.04-1.86 0-2.14 1.45-2.14 2.95v5.66H9.34V9h3.42v1.56h.05c.48-.9 1.64-1.85 3.37-1.85 3.6 0 4.27 2.37 4.27 5.45v6.29zM5.34 7.43a2.06 2.06 0 1 1 0-4.13 2.06 2.06 0 0 1 0 4.13zM7.12 20.45H3.56V9h3.56v11.45zM22.22 0H1.77C.79 0 0 .77 0 1.72v20.56C0 23.23.79 24 1.77 24h20.44c.98 0 1.78-.77 1.78-1.72V1.72C24 .77 23.2 0 22.22 0z"/>
    </svg>
  );
}

Object.assign(window, { Reveal, Counter, LogoMark, Arrow, LinkedInIcon });
