/* ============================================================
   <AnimatedCounter /> — counts from 0 → `value` when scrolled
   into view. Eased cubic, configurable formatter.
   ============================================================ */

function AnimatedCounter({
  value,
  prefix = "",
  suffix = "",
  duration = 1600,
  decimals = null,        // null = auto (0 if integer, 1 if float)
  formatter = null,        // (n) => string — overrides decimals/prefix/suffix
  className = "",
  delay = 0,
}) {
  const ref = React.useRef(null);
  const [display, setDisplay] = React.useState(0);
  const triggered = React.useRef(false);

  React.useEffect(() => {
    if (!ref.current) return;
    const obs = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (!e.isIntersecting || triggered.current) return;
        triggered.current = true;

        const target = Number(value) || 0;
        const start = performance.now() + delay;
        const tick = (ts) => {
          if (ts < start) { requestAnimationFrame(tick); return; }
          const t = Math.min(1, (ts - start) / duration);
          const eased = 1 - Math.pow(1 - t, 3);
          setDisplay(target * eased);
          if (t < 1) requestAnimationFrame(tick);
          else setDisplay(target);
        };
        requestAnimationFrame(tick);
      });
    }, { threshold: 0.4 });
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, [value, duration, delay]);

  let text;
  if (formatter) {
    text = formatter(display);
  } else {
    const d = decimals != null ? decimals : (Number.isInteger(value) ? 0 : 1);
    text = display.toFixed(d).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    text = `${prefix}${text}${suffix}`;
  }

  return <span ref={ref} className={className}>{text}</span>;
}

window.AnimatedCounter = AnimatedCounter;
