"use client";

import { useEffect, useRef, useState, useCallback } from "react";

interface CountUpNumberProps {
  value: number;
  suffix?: string;
  prefix?: string;
  duration?: number;
  className?: string;
}

export default function CountUpNumber({
  value,
  suffix = "",
  prefix = "",
  duration = 1500,
  className,
}: CountUpNumberProps) {
  const [displayValue, setDisplayValue] = useState(0);
  const [hasTriggered, setHasTriggered] = useState(false);
  const elementRef = useRef<HTMLSpanElement>(null);
  const animationRef = useRef<number | null>(null);

  const animate = useCallback(() => {
    const startTime = performance.now();

    const step = (currentTime: number) => {
      const elapsed = currentTime - startTime;
      const progress = Math.min(elapsed / duration, 1);

      // easeOut cubic
      const eased = 1 - Math.pow(1 - progress, 3);
      const current = eased * value;

      setDisplayValue(current);

      if (progress < 1) {
        animationRef.current = requestAnimationFrame(step);
      }
    };

    animationRef.current = requestAnimationFrame(step);
  }, [value, duration]);

  useEffect(() => {
    const element = elementRef.current;
    if (!element) return;

    const observer = new IntersectionObserver(
      (entries) => {
        const entry = entries[0];
        if (entry.isIntersecting && !hasTriggered) {
          setHasTriggered(true);
          animate();
        }
      },
      { threshold: 0.3 }
    );

    observer.observe(element);

    return () => {
      observer.disconnect();
      if (animationRef.current !== null) {
        cancelAnimationFrame(animationRef.current);
      }
    };
  }, [animate, hasTriggered]);

  const formatNumber = (num: number): string => {
    // If the target value has a decimal, show one decimal place
    if (value % 1 !== 0) {
      return num.toFixed(1);
    }
    return Math.floor(num).toLocaleString("ar-EG");
  };

  return (
    <span ref={elementRef} className={`tabular-nums ${className || ""}`}>
      {prefix}
      {formatNumber(displayValue)}
      {suffix}
    </span>
  );
}
