"use client";

import { animate, useInView, useMotionValue, useReducedMotion } from "motion/react";
import { useEffect, useRef, useState } from "react";

type Props = {
  value: number;
  suffix?: string;
  prefix?: string;
  /** Display label below the number. */
  label: string;
  /** Optional pre-formatted display override for the final state (e.g. "1,000+"). */
  display?: string;
};

function formatNumber(n: number): string {
  return Math.round(n).toLocaleString("en-US");
}

/**
 * Animates a number from 0 → `value` the first time the element is scrolled
 * into view. Uses motion/react's `useInView` + `useMotionValue` + `animate`.
 *
 * SSR-safe: renders the final number on first paint. When JS hydrates we
 * reset to 0 and re-run the animation on view. If the user prefers reduced
 * motion, we skip all animation and just show the final value.
 */
export function StatCounter({
  value,
  suffix = "",
  prefix = "",
  label,
  display,
}: Props) {
  const ref = useRef<HTMLDivElement>(null);
  const inView = useInView(ref, { once: true, amount: 0.6 });
  const shouldReduceMotion = useReducedMotion();
  const motionValue = useMotionValue(0);
  const finalText = display ?? formatNumber(value);
  const [rendered, setRendered] = useState<string>(finalText);
  const [hydrated, setHydrated] = useState(false);

  useEffect(() => {
    setHydrated(true);
  }, []);

  useEffect(() => {
    if (!hydrated) return;
    if (shouldReduceMotion) {
      setRendered(finalText);
      return;
    }
    // Keep showing the final value until the element scrolls into view;
    // only then reset to 0 and run the count-up animation. Previously we
    // reset to 0 whenever !inView, stranding users at "0" when the
    // intersection threshold never fired.
    if (!inView) return;
    motionValue.set(0);
    setRendered(formatNumber(0));
    const controls = animate(motionValue, value, {
      duration: 1.8,
      ease: [0.22, 1, 0.36, 1],
      onUpdate: (v) => setRendered(formatNumber(v)),
      onComplete: () => setRendered(finalText),
    });
    return () => controls.stop();
  }, [hydrated, inView, shouldReduceMotion, value, finalText, motionValue]);

  return (
    <div ref={ref} className="flex flex-col">
      <div className="font-display text-[40px] md:text-[52px] font-extrabold leading-none tracking-[-0.02em] text-white tabular-nums">
        {prefix}
        {rendered}
        {suffix}
      </div>
      <div className="mt-3 text-[13px] font-medium uppercase tracking-wider text-white/70">
        {label}
      </div>
    </div>
  );
}
