import React, { useEffect, useRef, useState } from 'react';
import { motion, useInView, useSpring, useTransform } from 'framer-motion';

export interface AnimatedCounterProps {
  /** The target value to count to */
  value: number;
  /** Duration of the animation in seconds */
  duration?: number;
  /** Number of decimal places to display */
  decimals?: number;
  /** Prefix to display before the number (e.g., "€", "$") */
  prefix?: string;
  /** Suffix to display after the number (e.g., "%", "/mes") */
  suffix?: string;
  /** Additional CSS classes */
  className?: string;
  /** Delay before animation starts (in seconds) */
  delay?: number;
  /** Whether to animate on mount or when in view */
  animateOnMount?: boolean;
}

/**
 * AnimatedCounter - Animates numbers counting up from 0 to target value
 *
 * Features:
 * - Smooth spring-based animation
 * - Configurable duration and delay
 * - Support for decimals, prefix, and suffix
 * - Triggers animation when scrolling into view
 * - Accessible with proper number formatting
 *
 * @example
 * <AnimatedCounter value={2000} prefix="€" suffix="/mes" />
 * <AnimatedCounter value={92} suffix="%" decimals={0} />
 */
export const AnimatedCounter: React.FC<AnimatedCounterProps> = ({
  value,
  duration = 2,
  decimals = 0,
  prefix = '',
  suffix = '',
  className = '',
  delay = 0,
  animateOnMount = false,
}) => {
  const ref = useRef<HTMLSpanElement>(null);
  const isInView = useInView(ref, { once: true, amount: 0.5 });
  const [hasAnimated, setHasAnimated] = useState(false);

  const shouldAnimate = animateOnMount || isInView;

  // Spring animation for smooth counting
  const spring = useSpring(0, {
    damping: 30,
    stiffness: 50,
    duration: duration * 1000,
  });

  const display = useTransform(spring, (current) =>
    current.toFixed(decimals)
  );

  useEffect(() => {
    if (shouldAnimate && !hasAnimated) {
      const timer = setTimeout(() => {
        spring.set(value);
        setHasAnimated(true);
      }, delay * 1000);

      return () => clearTimeout(timer);
    }
  }, [shouldAnimate, hasAnimated, value, spring, delay]);

  const [displayValue, setDisplayValue] = useState('0');

  useEffect(() => {
    const unsubscribe = display.on('change', (latest) => {
      setDisplayValue(latest);
    });
    return unsubscribe;
  }, [display]);

  return (
    <motion.span
      ref={ref}
      className={className}
      initial={{ opacity: 0, y: 20 }}
      animate={shouldAnimate ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
      transition={{ duration: 0.5, delay: delay }}
      aria-live="polite"
      aria-atomic="true"
    >
      {prefix}
      {displayValue}
      {suffix}
    </motion.span>
  );
};

export default AnimatedCounter;
