<template>
  <div class="server-category-picker">
    <div class="d-flex align-center flex-wrap ga-2 mb-2">
      <v-checkbox
        :model-value="selectAll"
        label="全选"
        density="compact"
        hide-details
        @update:model-value="toggleAll"
      />
      <v-text-field
        v-model="serverSearch"
        prepend-inner-icon="mdi-magnify"
        label="搜索服务器"
        density="compact"
        hide-details
        variant="outlined"
        rounded
        style="max-width: 220px"
        clearable
      />
      <v-chip v-if="model.length > 0" size="small" color="primary" variant="tonal" label>
        已选 {{ model.length }} 台
      </v-chip>
      <v-progress-circular v-if="loading" indeterminate size="18" width="2" />
    </div>

    <div class="picker-scroll" :style="{ maxHeight }">
      <div v-if="!loading && serversByCategory.length === 0" class="text-center text-medium-emphasis py-4">
        暂无服务器
      </div>
      <div v-for="group in serversByCategory" :key="group.category" class="mb-3">
        <div class="d-flex align-center px-1 mb-1">
          <v-btn
            size="x-small"
            variant="text"
            :color="isCategoryAllSelected(group.category) ? 'primary' : 'default'"
            @click="toggleCategory(group.category)"
          >
            <v-icon size="16" class="mr-1">
              {{ isCategoryAllSelected(group.category) ? 'mdi-checkbox-marked' : 'mdi-checkbox-blank-outline' }}
            </v-icon>
            {{ group.label }}
          </v-btn>
          <span class="text-caption text-medium-emphasis ml-1">
            ({{ groupSelectedCount(group) }}/{{ group.servers.length }})
          </span>
        </div>
        <v-row dense>
          <v-col v-for="s in group.servers" :key="s.id" cols="12" sm="6">
            <v-card
              :color="selectedSet.has(s.id) ? 'primary' : undefined"
              :variant="selectedSet.has(s.id) ? 'tonal' : 'outlined'"
              rounded="lg"
              class="pa-2 cursor-pointer"
              @click="toggleServer(s.id)"
            >
              <div class="d-flex align-center ga-2">
                <v-icon :color="serverOnlineColor(s.is_online)" size="10">mdi-circle</v-icon>
                <span class="text-body-2 font-weight-medium text-truncate">{{ s.name }}</span>
              </div>
              <div class="text-caption text-medium-emphasis text-truncate">{{ s.domain }}</div>
            </v-card>
          </v-col>
        </v-row>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
import { categoryDisplayLabel } from '@/composables/useServerCategories'
import { serverOnlineColor } from '@/composables/push/labels'
import type { ServerBrief } from '@/composables/useServerList'

const model = defineModel<number[]>({ default: () => [] })

const props = withDefaults(
  defineProps<{
    servers: ServerBrief[]
    loading?: boolean
    maxHeight?: string
  }>(),
  { loading: false, maxHeight: '280px' },
)

const serverSearch = ref('')

const selectedSet = computed(() => new Set(model.value))

const filteredServers = computed(() => {
  const q = serverSearch.value.trim().toLowerCase()
  if (!q) return props.servers
  return props.servers.filter(
    s =>
      s.name.toLowerCase().includes(q) ||
      (s.domain || '').toLowerCase().includes(q) ||
      (s.category || '').toLowerCase().includes(q),
  )
})

const serversByCategory = computed(() => {
  const groups: Record<string, ServerBrief[]> = {}
  for (const s of filteredServers.value) {
    const cat = s.category?.trim() || 'uncategorized'
    if (!groups[cat]) groups[cat] = []
    groups[cat].push(s)
  }
  return Object.entries(groups)
    .map(([category, list]) => ({
      category,
      label: categoryDisplayLabel(category),
      servers: [...list].sort((a, b) => a.name.localeCompare(b.name, 'zh')),
    }))
    .sort((a, b) => {
      if (a.category === 'uncategorized') return 1
      if (b.category === 'uncategorized') return -1
      return a.label.localeCompare(b.label, 'zh')
    })
})

const selectAll = computed(() => {
  const visible = filteredServers.value
  return visible.length > 0 && visible.every(s => selectedSet.value.has(s.id))
})

function groupSelectedCount(group: { servers: ServerBrief[] }): number {
  return group.servers.filter(s => selectedSet.value.has(s.id)).length
}

function isCategoryAllSelected(category: string): boolean {
  const group = serversByCategory.value.find(g => g.category === category)
  if (!group || group.servers.length === 0) return false
  return group.servers.every(s => selectedSet.value.has(s.id))
}

function emitIds(next: Set<number>) {
  model.value = [...next]
}

function toggleServer(id: number) {
  const next = new Set(model.value)
  if (next.has(id)) next.delete(id)
  else next.add(id)
  emitIds(next)
}

function toggleCategory(category: string) {
  const group = serversByCategory.value.find(g => g.category === category)
  if (!group) return
  const next = new Set(model.value)
  const allSelected = group.servers.every(s => next.has(s.id))
  for (const s of group.servers) {
    if (allSelected) next.delete(s.id)
    else next.add(s.id)
  }
  emitIds(next)
}

function toggleAll() {
  const visible = filteredServers.value
  const next = new Set(model.value)
  const allSelected = visible.length > 0 && visible.every(s => next.has(s.id))
  for (const s of visible) {
    if (allSelected) next.delete(s.id)
    else next.add(s.id)
  }
  emitIds(next)
}
</script>

<style scoped>
.picker-scroll {
  overflow-y: auto;
  padding-right: 4px;
}
</style>
