<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { http } from '@/api'
import WatchTrendChart, { type WatchTrendPoint } from '@/components/watch/WatchTrendChart.vue'
import WatchProbeRecordsTable from '@/components/watch/WatchProbeRecordsTable.vue'
import { useWatchPins } from '@/composables/useWatchPins'

defineOptions({ name: 'WatchMetricsPage' })

const WATCH_SLOT_COUNT = 4

const route = useRoute()
const tab = ref('trend')
const hours = ref(24)
const points = ref<WatchTrendPoint[]>([])
const loading = ref(false)
const selectedSeries = ref<Array<'cpu_pct' | 'mem_pct' | 'disk_pct' | 'net_up_bps' | 'net_down_bps'>>([
  'cpu_pct', 'mem_pct', 'disk_pct', 'net_down_bps',
])

const { slots, refreshPins } = useWatchPins()

const slotPanels = computed(() =>
  Array.from({ length: WATCH_SLOT_COUNT }, (_, slotIndex) => {
    const slot = slots.value.find((s) => s.slot_index === slotIndex)
    const empty = !slot || slot.empty
    return {
      slotIndex,
      empty,
      serverId: empty ? null : (slot.server_id ?? null),
      serverName: empty ? '' : (slot.server_name || `ID ${slot.server_id}`),
    }
  }),
)

const pinnedServerIds = computed(() =>
  slotPanels.value
    .map((p) => p.serverId)
    .filter((id): id is number => id != null),
)

const pointsByServer = computed(() => {
  const map = new Map<number, WatchTrendPoint[]>()
  for (const p of points.value) {
    const sid = p.server_id
    if (sid == null) continue
    const list = map.get(sid) ?? []
    list.push(p)
    map.set(sid, list)
  }
  return map
})

async function loadTrend() {
  const ids = pinnedServerIds.value
  if (!ids.length) {
    points.value = []
    return
  }
  loading.value = true
  try {
    const data = await http.get<{ points: WatchTrendPoint[] }>('/watch/metrics', {
      server_ids: ids.join(','),
      hours: hours.value,
    })
    points.value = data.points || []
  } finally {
    loading.value = false
  }
}

onMounted(async () => {
  await refreshPins()
  const qTab = route.query.tab
  if (qTab === 'records') tab.value = 'records'
})

watch([pinnedServerIds, hours], loadTrend, { immediate: true, deep: true })
</script>

<template>
  <v-container fluid class="pa-4 pa-md-6">
    <div class="d-flex align-center mb-4">
      <h1 class="text-h6">监测历史</h1>
      <v-chip size="x-small" variant="tonal" class="ml-2" label>4 槽同时展示</v-chip>
      <v-spacer />
      <v-btn variant="text" prepend-icon="mdi-arrow-left" :to="{ name: 'Servers' }">返回服务器</v-btn>
    </div>

    <v-card elevation="0" border rounded="lg">
      <v-tabs v-model="tab" color="primary">
        <v-tab value="trend">资源趋势</v-tab>
        <v-tab value="records">探针记录</v-tab>
      </v-tabs>
      <v-divider />
      <v-card-text>
        <v-window v-model="tab">
          <v-window-item value="trend">
            <div class="d-flex flex-wrap ga-2 mb-4">
              <v-btn-toggle v-model="hours" mandatory density="compact" variant="outlined" divided>
                <v-btn :value="1" size="small">1h</v-btn>
                <v-btn :value="6" size="small">6h</v-btn>
                <v-btn :value="24" size="small">24h</v-btn>
                <v-btn :value="168" size="small">7d</v-btn>
              </v-btn-toggle>
              <v-select
                v-model="selectedSeries"
                :items="[
                  { title: 'CPU %', value: 'cpu_pct' },
                  { title: '内存 %', value: 'mem_pct' },
                  { title: '磁盘 %', value: 'disk_pct' },
                  { title: '上行', value: 'net_up_bps' },
                  { title: '下行', value: 'net_down_bps' },
                ]"
                item-title="title"
                item-value="value"
                label="曲线（各槽共用）"
                multiple
                chips
                density="compact"
                hide-details
                variant="outlined"
                style="min-width: 280px"
              />
            </div>
            <v-progress-linear v-if="loading" indeterminate class="mb-2" />
            <v-row dense>
              <v-col
                v-for="panel in slotPanels"
                :key="panel.slotIndex"
                cols="12"
                md="6"
              >
                <v-card variant="outlined" rounded="lg" class="watch-metrics-slot pa-3">
                  <div class="d-flex align-center mb-2">
                    <v-chip size="x-small" variant="tonal" color="info" label>
                      槽 {{ panel.slotIndex + 1 }}
                    </v-chip>
                    <span class="text-subtitle-2 text-truncate ml-2" :title="panel.serverName">
                      {{ panel.empty ? '未占用' : panel.serverName }}
                    </span>
                  </div>
                  <WatchTrendChart
                    v-if="!panel.empty && panel.serverId != null && (pointsByServer.get(panel.serverId)?.length ?? 0) > 0"
                    :points="pointsByServer.get(panel.serverId!) ?? []"
                    :series="selectedSeries"
                    :height="280"
                  />
                  <div
                    v-else-if="panel.empty"
                    class="text-center text-medium-emphasis watch-metrics-slot__empty"
                  >
                    未添加监测
                  </div>
                  <div
                    v-else
                    class="text-center text-medium-emphasis watch-metrics-slot__empty"
                  >
                    暂无趋势数据（需开启监测并等待探针采样）
                  </div>
                </v-card>
              </v-col>
            </v-row>
          </v-window-item>
          <v-window-item value="records">
            <WatchProbeRecordsTable :hours="hours" />
          </v-window-item>
        </v-window>
      </v-card-text>
    </v-card>
  </v-container>
</template>

<style scoped>
.watch-metrics-slot {
  min-height: 320px;
}
.watch-metrics-slot__empty {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 280px;
  padding: 1rem;
}
</style>
