import React, { useEffect, useRef, useState } from 'react';
import { Animated, Easing, TextStyle } from 'react-native';

type AnimatedNumberProps = {
  value: number; // 最终值
  durationMs?: number;
  format?: (v: number) => string;
  style?: TextStyle;
  /** 当该值变化时，从0重新动画 */
  resetToken?: unknown;
};

export function AnimatedNumber({
  value,
  durationMs = 300,
  format,
  style,
  resetToken,
}: AnimatedNumberProps) {
  const opacity = useRef(new Animated.Value(1)).current;
  const [display, setDisplay] = useState<string>('0');
  const [currentValue, setCurrentValue] = useState(0);

  useEffect(() => {
    // 如果值没有变化，不执行动画
    if (value === currentValue && resetToken === undefined) {
      return;
    }

    // 停止当前动画
    opacity.stopAnimation(() => {
      // 创建优雅的透明度变化动画
      const fadeOut = Animated.timing(opacity, {
        toValue: 0.2, // 淡出到较低透明度
        duration: durationMs * 0.4, // 淡出占总时长的40%
        easing: Easing.out(Easing.quad),
        useNativeDriver: false,
      });

      const fadeIn = Animated.timing(opacity, {
        toValue: 1,
        duration: durationMs * 0.6, // 淡入占总时长的60%
        easing: Easing.out(Easing.quad),
        useNativeDriver: false,
      });

      // 在淡出完成时更新数字显示
      fadeOut.start(() => {
        // 更新当前值和显示
        setCurrentValue(value);
        setDisplay(format ? format(value) : `${Math.round(value)}`);

        // 然后淡入新数字
        fadeIn.start();
      });
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [value, resetToken]);

  // 初始化显示值
  useEffect(() => {
    if (currentValue !== value) {
      setCurrentValue(value);
      setDisplay(format ? format(value) : `${Math.round(value)}`);
    }
  }, [value, format, currentValue]);

  return (
    <Animated.Text
      style={[
        style,
        {
          opacity: opacity
        }
      ]}
    >
      {display}
    </Animated.Text>
  );
}


