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

interface Props {
  end: number
  duration?: number
  suffix?: string
  decimals?: number
}

const props = withDefaults(defineProps<Props>(), {
  duration: 2000,
  suffix: '',
  decimals: 0,
})

const count = ref(0)
const refEl = ref<HTMLDivElement | null>(null)
let hasAnimated = false
let rafId: number | null = null
let observer: IntersectionObserver | null = null

onMounted(() => {
  observer = new IntersectionObserver(
    (entries) => {
      if (entries[0].isIntersecting && !hasAnimated) {
        hasAnimated = true
        let startTime: number | null = null

        const animate = (currentTime: number) => {
          if (!startTime) startTime = currentTime
          const progress = Math.min((currentTime - startTime) / props.duration, 1)
          const easeProgress = 1 - Math.pow(1 - progress, 4)
          count.value = props.end * easeProgress

          if (progress < 1) {
            rafId = requestAnimationFrame(animate)
          } else {
            count.value = props.end
          }
        }

        rafId = requestAnimationFrame(animate)
      }
    },
    { threshold: 0.5 }
  )

  if (refEl.value) {
    observer.observe(refEl.value)
  }
})

onUnmounted(() => {
  if (observer && refEl.value) observer.disconnect()
  if (rafId) cancelAnimationFrame(rafId)
})
</script>

<template>
  <div
    ref="refEl"
    class="text-4xl md:text-5xl font-bold text-apple-dark mb-2 transition-transform group-hover:scale-110 duration-300 tabular-nums"
  >
    {{ count.toFixed(props.decimals) }}
    <span v-if="props.suffix" class="text-2xl ml-1 font-medium text-gray-400">{{ props.suffix }}</span>
  </div>
</template>
