/* eslint-disable */
/* global React */
const { useState, useEffect, useRef } = React;

/* ============================================================
   useInView — IntersectionObserver hook (returns [ref, inView])
   ============================================================ */
function useInView(opts = {}) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (typeof IntersectionObserver === 'undefined') { setInView(true); return; }
    const io = new IntersectionObserver(
      (entries) => {
        for (const e of entries) {
          if (e.isIntersecting) {
            setInView(true);
            if (opts.once !== false) io.disconnect();
            return;
          }
        }
      },
      { threshold: opts.threshold ?? 0.18, rootMargin: opts.rootMargin ?? '0px 0px -10% 0px' }
    );
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return [ref, inView];
}

/* ============================================================
   prefers-reduced-motion
   ============================================================ */
const prefersReducedMotion =
  typeof window !== 'undefined' && window.matchMedia
    ? window.matchMedia('(prefers-reduced-motion: reduce)').matches
    : false;

/* ============================================================
   Reveal — fades child in from below on scroll-into-view
   ============================================================ */
function Reveal({ children, delay = 0, y = 18, as: As = 'div', className = '', style = {}, threshold }) {
  const [ref, inView] = useInView({ threshold });
  const visible = inView || prefersReducedMotion;
  return (
    <As
      ref={ref}
      className={className}
      style={{
        ...style,
        opacity: visible ? 1 : 0,
        transform: visible ? 'translate3d(0,0,0)' : `translate3d(0,${y}px,0)`,
        transition: `opacity 700ms cubic-bezier(0.16,1,0.3,1) ${delay}ms, transform 700ms cubic-bezier(0.16,1,0.3,1) ${delay}ms`,
        willChange: 'opacity, transform',
      }}
    >
      {children}
    </As>
  );
}

/* ============================================================
   Stagger — staggers immediate children Reveal-style
   children must be an array of React elements
   ============================================================ */
function Stagger({ children, base = 0, step = 100, y = 16, className = '', as: As = 'div', style = {} }) {
  const [ref, inView] = useInView();
  const visible = inView || prefersReducedMotion;
  const items = React.Children.toArray(children);
  return (
    <As ref={ref} className={className} style={style}>
      {items.map((child, i) => (
        <div
          key={i}
          style={{
            opacity: visible ? 1 : 0,
            transform: visible ? 'translate3d(0,0,0)' : `translate3d(0,${y}px,0)`,
            transition: `opacity 700ms cubic-bezier(0.16,1,0.3,1) ${base + i * step}ms, transform 700ms cubic-bezier(0.16,1,0.3,1) ${base + i * step}ms`,
            willChange: 'opacity, transform',
          }}
        >
          {child}
        </div>
      ))}
    </As>
  );
}

/* ============================================================
   CountUp — animates from 0 to value on scroll-into-view
   ============================================================ */
function CountUp({ to = 0, suffix = '', prefix = '', duration = 1600 }) {
  const [ref, inView] = useInView({ threshold: 0.4 });
  const [n, setN] = useState(0);
  useEffect(() => {
    if (!inView) return;
    if (prefersReducedMotion) { setN(to); return; }
    let raf;
    const start = performance.now();
    const ease = (t) => 1 - Math.pow(1 - t, 3);
    const tick = (now) => {
      const t = Math.min(1, (now - start) / duration);
      setN(Math.round(to * ease(t)));
      if (t < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [inView, to, duration]);
  return <span ref={ref}>{prefix}{n.toLocaleString()}{suffix}</span>;
}

/* ============================================================
   Bars motif
   ============================================================ */
function Bars({ size = 'md', className = '' }) {
  const w = size === 'sm' ? 24 : size === 'lg' ? 72 : 40;
  const h = size === 'sm' ? 3 : size === 'lg' ? 8 : 5;
  const g = size === 'sm' ? 3 : size === 'lg' ? 6 : 4;
  return (
    <span
      className={`bars ${className}`}
      style={{ width: w, display: 'inline-flex', flexDirection: 'column', gap: g, flexShrink: 0 }}
      aria-hidden="true"
    >
      <i style={{ display: 'block', height: h, background: 'var(--gold)', width: '100%', borderRadius: 1 }}></i>
      <i style={{ display: 'block', height: h, background: 'var(--gold)', width: '65%', borderRadius: 1 }}></i>
      <i style={{ display: 'block', height: h, background: 'var(--gold)', width: '38%', borderRadius: 1 }}></i>
    </span>
  );
}

Object.assign(window, { useInView, prefersReducedMotion, Reveal, Stagger, CountUp, Bars });
