<template>
  <div class="percentage-display">
    <div v-for="(item, index) in data" :key="index" class="percentage-item">
      <div class="percentage-bar">
        <div class="percentage-value">
          {{
            formatNumber(
              displayValues[index],
              item.decimals || props.decimals,
              item.unit || props.unit,
              isIntegerList[index]
            )
          }}
        </div>
        <div class="percentage-label">{{ item.label }}</div>
        <div class="percentage-desc">{{ item.description }}</div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'

// Props
const props = withDefaults(
  defineProps<{
    data: Array<{
      label: string
      value: number
      description: string
      unit?: string
      decimals?: number
    }>
    unit?: string
    decimals?: number
    useThousandsSeparator?: boolean
  }>(),
  {
    unit: '%',
    decimals: 1,
    useThousandsSeparator: true,
  }
)

// 显示值，用于动画效果
const displayValues = ref<number[]>([])
// 记录每个数据项是否为整数
const isIntegerList = ref<boolean[]>([])

// 数字格式化函数
const formatNumber = (
  value: number,
  decimals: number,
  unit: string,
  isOriginalInteger: boolean
): string => {
  // 格式化数字
  let formatted: string
  if (isOriginalInteger) {
    // 原始数据是整数，无论动画过程中是否有小数，都显示为整数
    formatted = Math.round(value).toString()
  } else {
    // 原始数据不是整数，保留指定小数位数
    formatted = value.toFixed(decimals)
  }

  // 分割整数部分和小数部分
  const [integerPart, decimalPart] = formatted.split('.')

  // 添加千位分隔符
  const integerWithSeparator = props.useThousandsSeparator
    ? integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
    : integerPart

  // 组合整数部分、小数部分和单位
  if (decimalPart) {
    return `${integerWithSeparator}.${decimalPart}${unit}`
  } else {
    return `${integerWithSeparator}${unit}`
  }
}

// 动画配置
const animationDuration = 1200

// 动画函数
const animateValue = (start: number, end: number, index: number) => {
  const startTime = performance.now()

  const animate = (currentTime: number) => {
    const elapsed = currentTime - startTime
    const progress = Math.min(elapsed / animationDuration, 1)

    // 缓动函数：easeOutQuad
    const easeOutQuad = (t: number) => t * (2 - t)
    const easedProgress = easeOutQuad(progress)

    displayValues.value[index] = start + (end - start) * easedProgress

    if (progress < 1) {
      requestAnimationFrame(animate)
    }
  }

  requestAnimationFrame(animate)
}

// 初始化和更新动画
const startAnimations = () => {
  displayValues.value = props.data.map(() => 0)
  // 记录每个数据项是否为整数
  isIntegerList.value = props.data.map((item) => Number.isInteger(item.value))

  // 为每个百分比启动动画
  props.data.forEach((item, index) => {
    setTimeout(() => {
      animateValue(0, item.value, index)
    }, index * 200) // 错开动画开始时间，增加视觉效果
  })
}

// 监听数据变化，重新启动动画
watch(
  () => props.data,
  () => {
    startAnimations()
  },
  { deep: true, immediate: true }
)

// 组件挂载时启动动画
onMounted(() => {
  startAnimations()
})
</script>

<style lang="scss" scoped>
// SCSS变量定义
$text-color: rgba(0, 255, 230, 0.7);
$percentage-color: #01ffe6;

.percentage-display {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 30px;

  .percentage-item {
    flex: 1;
    text-align: center;
    position: relative;
    height: 150px;

    .percentage-bar {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100%;
      width: calc(100% - 12px);
    }

    &:last-child .percentage-bar {
      width: 100%;
    }

    &:not(:last-child)::after {
      content: '';
      position: absolute;
      right: 0;
      top: 0;
      height: 100%;
      width: 2px;
      margin: 0 10px;
      background: url('@/assets/images/vertical_line.png') center no-repeat;
      background-size: 100% 100%;
    }

    .percentage-value {
      font-size: 44px;
      font-weight: 500;
      color: $percentage-color;
      line-height: 56px;
      letter-spacing: 2px;
      margin-bottom: 8px;
      white-space: nowrap;
    }

    .percentage-label {
      font-size: 30px;
      font-weight: 500;
      color: $text-color;
      letter-spacing: 1px;
      margin-bottom: 8px;
      white-space: nowrap;
    }

    .percentage-desc {
      font-size: 26px;
      font-weight: 500;
      letter-spacing: 1px;
      color: rgba(0, 255, 230, 0.3);
      white-space: nowrap;
    }
  }
}
</style>
