<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import WatchSlotCard from '@/components/watch/WatchSlotCard.vue'
import WatchProcessDrawer from '@/components/watch/WatchProcessDrawer.vue'
import WatchSlotPickDialog from '@/components/watch/WatchSlotPickDialog.vue'
import { useWatchPins, type WatchSlot } from '@/composables/useWatchPins'
import { useSnackbar } from '@/composables/useSnackbar'
import { formatApiError } from '@/utils/apiError'
import { http } from '@/api'
import { watchTtlShortLabel, type WatchTtlMinutes } from '@/constants/watchTtl'

const router = useRouter()
const snackbar = useSnackbar()
const { slots, loading, refreshPins, removeSlot, pinServer, setSlotMonitoring, setSlotTtl } = useWatchPins()

const processDrawer = ref(false)
const processSlot = ref<WatchSlot | null>(null)
const showPickDialog = ref(false)
const pickSlotIndex = ref<number | null>(null)
const pickLoading = ref(false)
const psutilLoadingSlot = ref<number | null>(null)

onMounted(() => {
  refreshPins()
})

async function onRemove(slotIndex: number) {
  try {
    await removeSlot(slotIndex)
    snackbar(`已移除监测 · 槽 ${slotIndex + 1}`, 'success')
  } catch (e: unknown) {
    snackbar(formatApiError(e, '移除监测失败'), 'error')
  }
}

async function onMonitoring(slotIndex: number, enabled: boolean) {
  try {
    await setSlotMonitoring(slotIndex, enabled)
    snackbar(enabled ? `已开启实时监测 · 槽 ${slotIndex + 1}` : `已暂停实时监测 · 槽 ${slotIndex + 1}`, 'success')
  } catch (e: unknown) {
    snackbar(formatApiError(e, '更新监测开关失败'), 'error')
  }
}

async function onTtl(slotIndex: number, minutes: WatchTtlMinutes) {
  const slot = slots.value.find((s) => s.slot_index === slotIndex)
  if (!slot || slot.empty || slot.ttl_minutes === minutes) return
  try {
    await setSlotTtl(slotIndex, minutes)
    snackbar(`监测时长已设为 ${watchTtlShortLabel(minutes)} · 槽 ${slotIndex + 1}`, 'success')
  } catch (e: unknown) {
    snackbar(formatApiError(e, '更新监测时长失败'), 'error')
  }
}

function openProcesses(slot: WatchSlot) {
  processSlot.value = slot
  processDrawer.value = true
}

function openHistory(slot: WatchSlot) {
  router.push({
    name: 'WatchMetrics',
    query: {
      server_id: String(slot.server_id),
      session_id: slot.session_id ? String(slot.session_id) : undefined,
    },
  })
}

function onPickSlot(slotIndex: number) {
  pickSlotIndex.value = slotIndex
  showPickDialog.value = true
}

async function onInstallPsutil(slotIndex: number) {
  const slot = slots.value.find((s) => s.slot_index === slotIndex)
  if (!slot?.server_id) return
  psutilLoadingSlot.value = slotIndex
  try {
    const data = await http.post<{ message?: string }>(
      `/watch/servers/${slot.server_id}/install-psutil`,
      {},
    )
    snackbar(data.message || 'psutil 安装成功', 'success')
    await refreshPins()
  } catch (e: unknown) {
    snackbar(formatApiError(e, '安装 psutil 失败'), 'error')
  } finally {
    psutilLoadingSlot.value = null
  }
}

async function onPickServer(serverId: number) {
  if (pickSlotIndex.value == null) return
  pickLoading.value = true
  try {
    const res = await pinServer(serverId, { slotIndex: pickSlotIndex.value })
    if (res.ok) {
      snackbar(`已加入监测 · 槽 ${pickSlotIndex.value + 1}`, 'success')
      showPickDialog.value = false
    } else if (res.full) {
      snackbar('监测槽已满，请先移除一台', 'warning')
    } else {
      snackbar(res.error || '加入监测失败', 'error')
    }
  } finally {
    pickLoading.value = false
  }
}
</script>

<template>
  <div class="watch-slot-row mb-4">
    <div class="d-flex align-center mb-2">
      <span class="text-subtitle-2">实时监测</span>
      <v-chip size="x-small" variant="tonal" class="ml-2" label>最多 4 台 · 默认 30 分 · 暂停不占 TTL</v-chip>
      <v-spacer />
      <v-btn size="small" variant="text" prepend-icon="mdi-history" :to="{ name: 'WatchMetrics' }">
        监测历史
      </v-btn>
      <v-btn icon="mdi-refresh" size="small" variant="text" :loading="loading" @click="refreshPins" />
    </div>
    <v-row dense>
      <v-col v-for="slot in slots" :key="slot.slot_index" cols="12" sm="6" lg="3">
        <WatchSlotCard
          :slot="slot"
          :psutil-install-loading="psutilLoadingSlot === slot.slot_index"
          @remove="onRemove"
          @processes="openProcesses"
          @history="openHistory"
          @pick="onPickSlot"
          @monitoring="onMonitoring"
          @ttl="onTtl"
          @install-psutil="onInstallPsutil"
        />
      </v-col>
    </v-row>
    <WatchProcessDrawer v-model="processDrawer" :slot-data="processSlot" />
    <WatchSlotPickDialog
      v-model="showPickDialog"
      :slot-index="pickSlotIndex"
      :loading="pickLoading"
      @pick="onPickServer"
    />
  </div>
</template>
