<script setup lang="ts">
import { NSelect, NSpin } from 'naive-ui'
import { computed, ref, watch } from 'vue'

import { getCosts } from '@/api/analytics'
import CostChart from '@/components/CostChart.vue'
import EmptyCard from '@/components/EmptyCard.vue'
import FootNote from '@/components/FootNote.vue'
import { useAsync } from '@/composables/useAsync'

const props = defineProps<{ cfgId: number }>()

const rangeDays = ref(14)
const rangeOptions = [
  { label: '近 14 天', value: 14 },
  { label: '近 30 天', value: 30 },
]

const costs = useAsync(() => getCosts(props.cfgId, { granularity: 'DAILY', groupBy: 'service' }))
watch(rangeDays, () => void costs.run())

const daily = computed(() => {
  const byDay = new Map<string, number>()
  for (const item of costs.data.value ?? []) {
    const day = item.timeStart.slice(5, 10)
    byDay.set(day, (byDay.get(day) ?? 0) + item.computedAmount)
  }
  const labels = [...byDay.keys()].sort()
  return { labels, values: labels.map((l) => +(byDay.get(l) ?? 0).toFixed(2)) }
})

const total = computed(() => daily.value.values.reduce((s, v) => s + v, 0))

const byService = computed(() => {
  const map = new Map<string, number>()
  for (const item of costs.data.value ?? []) {
    map.set(item.groupValue, (map.get(item.groupValue) ?? 0) + item.computedAmount)
  }
  const rows = [...map.entries()].sort((a, b) => b[1] - a[1])
  const max = rows[0]?.[1] ?? 1
  return rows.map(([name, amount]) => ({
    name,
    amount,
    pct: total.value ? Math.round((amount / total.value) * 100) : 0,
    barWidth: `${Math.round((amount / max) * 100)}%`,
  }))
})
</script>

<template>
  <div class="panel">
    <div class="flex flex-wrap items-center gap-2.5 border-b border-line-soft px-4.5 py-3.5">
      <div class="text-sm font-semibold">成本分析</div>
      <div class="flex-1" />
      <div class="w-28">
        <NSelect v-model:value="rangeDays" size="small" :options="rangeOptions" />
      </div>
    </div>

    <div v-if="costs.loading.value" class="flex items-center justify-center py-14">
      <NSpin size="small" />
    </div>
    <template v-else-if="costs.data.value?.length">
      <div class="flex flex-wrap items-baseline gap-2.5 px-4.5 pt-3.5">
        <div class="text-[26px] font-semibold tabular-nums">${{ total.toFixed(2) }}</div>
        <div class="text-[12.5px] text-ink-3">
          {{ daily.labels[0] }} 至 {{ daily.labels.at(-1) }} 合计
        </div>
      </div>
      <div class="px-3 pb-1">
        <CostChart :labels="daily.labels" :values="daily.values" />
      </div>

      <div class="border-t border-line-soft px-4.5 py-3">
        <div class="mb-2 flex items-center justify-between">
          <div class="text-[13px] font-semibold">按服务拆分</div>
          <div class="text-[12.5px] text-ink-3">本期合计 ${{ total.toFixed(2) }}</div>
        </div>
        <div
          v-for="svc in byService"
          :key="svc.name"
          class="flex items-center gap-3 py-1.5 max-md:gap-2"
        >
          <div class="w-32 flex-none truncate text-[13px] max-md:w-24" :title="svc.name">
            {{ svc.name }}
          </div>
          <div class="h-1.5 min-w-0 flex-1 overflow-hidden rounded-full bg-line-soft">
            <div class="h-full rounded-full bg-chart" :style="{ width: svc.barWidth }" />
          </div>
          <div class="w-17 flex-none text-right text-[13px] tabular-nums">
            ${{ svc.amount.toFixed(2) }}
          </div>
          <div class="w-10 flex-none text-right text-xs tabular-nums text-ink-3">{{ svc.pct }}%</div>
        </div>
      </div>
    </template>
    <EmptyCard
      v-else
      title="暂无成本数据"
      note="试用租户无消费时成本为空；Usage API 数据通常延迟数小时至一天"
    />
    <FootNote>
      每日 03:30 自动同步 Usage API · 本地快照 · 免费类别租户不参与成本同步 · 点击刷新可即时拉取
    </FootNote>
  </div>
</template>
