<template>
  <div class="elderly-horizontal-progress">
    <div v-for="(item, index) in processedData" :key="index" class="progress-item">
      <span class="progress-label" :style="{ color: item.color }">{{ item.label }}</span>
      <el-progress
        :percentage="Number(displayValues[index].toFixed(1))"
        :color="item.color"
        :stroke-width="14"
      >
        <template #default>
          <span class="progress-value" :style="{ color: item.color }"
            >{{ Math.round(displayValuesValue[index]) }}人</span
          >
        </template>
      </el-progress>
    </div>
  </div>
</template>

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

interface ProcessedData {
  label: string
  value: number
  color: string
  originalValue: number
}

const props = defineProps<{
  data: number[]
}>()

const animationDuration = 1200

const displayValues = ref<number[]>([])
const displayValuesValue = ref<number[]>([])

const processedData = computed<ProcessedData[]>(() => {
  const maxValue = Math.max(...props.data)
  const fullValue = maxValue / 0.8

  const colors = ['#01ffe6', 'rgba(255, 255, 0, 0.8)', 'rgba(255, 165, 0, 0.8)']
  const labels = ['全自理老人', '半自理老人', '全护理老人']

  return props.data.map((value, index) => ({
    label: labels[index],
    value: (value / fullValue) * 100,
    color: colors[index],
    originalValue: value,
  }))
})

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)

    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 animateValueNumber = (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)

    const easeOutQuad = (t: number) => t * (2 - t)
    const easedProgress = easeOutQuad(progress)

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

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

  requestAnimationFrame(animate)
}

const startAnimations = () => {
  displayValues.value = processedData.value.map(() => 0)
  displayValuesValue.value = processedData.value.map(() => 0)

  processedData.value.forEach((item, index) => {
    setTimeout(() => {
      animateValue(0, item.value, index)
      animateValueNumber(0, item.originalValue, index)
    }, index * 200)
  })
}

watch(
  () => props.data,
  () => {
    startAnimations()
  },
  { deep: true, immediate: true }
)

onMounted(() => {
  startAnimations()
})
</script>

<style lang="scss" scoped>
$text-color: #00ffe6;
$track-color: #282c38;

.elderly-horizontal-progress {
  width: 100%;

  .progress-item {
    margin-bottom: 26px;
    display: flex;
    justify-content: space-between;
    align-items: center;

    .progress-label {
      width: 160px;
      margin-right: 12px;
      font-size: 30px;
      color: $text-color;
    }

    :deep(.el-progress) {
      flex: 1;

      .el-progress__text {
        flex-shrink: 0 !important;
        width: 150px;
        margin-left: 24px;
        font-size: 30px !important;
        text-align: right;
      }
    }

    :deep(.el-progress-bar__outer) {
      background-color: $track-color;
      background: linear-gradient(0deg, rgba(50, 125, 118, 0.31) 0%, rgba(0, 255, 230, 0.2) 100%);
      box-shadow: inset -2px 0px 2px 0px rgba(0, 255, 230, 0.46);
    }
  }
}
</style>
