"use client";

import gsap from "gsap";
import { useLayoutEffect, useRef } from "react";

type Props = {
  value: number;
  duration?: number;
  prefix?: string;
  suffix?: string;
  formatter?: (v: number) => string;
  className?: string;
};

const defaultFormatter = (v: number) =>
  Math.round(v).toLocaleString("en-US");

export function AnimatedCounter({
  value,
  duration = 1.4,
  prefix = "",
  suffix = "",
  formatter = defaultFormatter,
  className,
}: Props) {
  const ref = useRef<HTMLSpanElement>(null);
  const proxy = useRef({ v: 0 });

  useLayoutEffect(() => {
    const reduced =
      typeof window !== "undefined" &&
      window.matchMedia("(prefers-reduced-motion: reduce)").matches;

    if (!ref.current) return;
    if (reduced) {
      ref.current.textContent = `${prefix}${formatter(value)}${suffix}`;
      return;
    }

    const target = proxy.current;
    const tween = gsap.to(target, {
      v: value,
      duration,
      ease: "power2.out",
      onUpdate: () => {
        if (ref.current) {
          ref.current.textContent = `${prefix}${formatter(target.v)}${suffix}`;
        }
      },
    });

    return () => {
      tween.kill();
      target.v = value;
    };
  }, [value, duration, prefix, suffix, formatter]);

  return <span ref={ref} className={className}>{prefix}0{suffix}</span>;
}
