"use client";

import { useLayoutEffect, useRef } from "react";

import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";

gsap.registerPlugin(ScrollTrigger);

type StatCounterProps = {
  value: number;
  suffix?: string;
  prefix?: string;
  /** Render without thousand separators (e.g. a year like 2000). */
  plain?: boolean;
  className?: string;
};

const fmt = (n: number, plain: boolean) =>
  plain ? String(n) : n.toLocaleString("en-MY");

/** Counts up once when scrolled into view. Static under reduced motion. */
export default function StatCounter({
  value,
  suffix = "",
  prefix = "",
  plain = false,
  className,
}: StatCounterProps) {
  const ref = useRef<HTMLSpanElement | null>(null);

  useLayoutEffect(() => {
    const el = ref.current;
    if (!el) return;

    const mq = gsap.matchMedia();
    mq.add("(prefers-reduced-motion: no-preference)", () => {
      const state = { v: 0 };
      const tween = gsap.to(state, {
        v: value,
        duration: 1.6,
        ease: "power2.out",
        scrollTrigger: {
          trigger: el,
          start: "top 85%",
          once: true,
        },
        onUpdate: () => {
          el.textContent = `${prefix}${fmt(Math.round(state.v), plain)}${suffix}`;
        },
      });
      return () => {
        tween.scrollTrigger?.kill();
        tween.kill();
      };
    });

    return () => mq.revert();
  }, [value, prefix, suffix, plain]);

  return (
    <span ref={ref} className={className}>
      {`${prefix}${fmt(value, plain)}${suffix}`}
    </span>
  );
}
