<template>
  <v-container fluid class="pa-6">
    <!-- Stats Cards -->
    <v-row>
      <v-col cols="12" sm="6" lg="3" v-for="stat in stats" :key="stat.label">
        <v-list elevation="0" lines="two" rounded="lg" border>
          <v-list-item>
            <v-list-item-title class="text-body-small">{{ stat.label }}</v-list-item-title>
            <v-list-item-title>{{ stat.value }}</v-list-item-title>
            <template #append>
              <v-icon :color="stat.color" size="30">{{ stat.icon }}</v-icon>
            </template>
          </v-list-item>
        </v-list>
      </v-col>
    </v-row>

    <!-- Server Table -->
    <v-card elevation="0" rounded="lg" class="mt-4" border>
      <v-card-title class="d-flex align-center">
        服务器列表
        <v-spacer />
          <v-text-field
          v-model="search"
          prepend-inner-icon="mdi-magnify"
          label="搜索..."
          density="compact"
          hide-details
          rounded
          style="max-width: 240px"
          variant="outlined"
          @update:model-value="onSearch"
        />
        <v-btn color="primary" variant="flat" class="ml-3" prepend-icon="mdi-plus" size="small" @click="showAdd = true">
          添加
        </v-btn>
        <v-btn variant="tonal" class="ml-2" prepend-icon="mdi-download" size="small" @click="exportCSV">
          导出CSV
        </v-btn>
        <v-btn variant="tonal" class="ml-2" prepend-icon="mdi-file-import" size="small" @click="showImport = true">
          导入
        </v-btn>
      </v-card-title>

      <!-- Batch Actions -->
      <v-card v-if="selectedIds.size > 0" class="mx-4 mb-2" color="primary" variant="tonal" rounded="lg">
        <v-card-text class="d-flex align-center py-2">
          <span class="text-body-2 mr-4">已选择 {{ selectedIds.size }} 台服务器</span>
          <v-spacer />
          <v-btn size="small" variant="text" @click="batchHealthCheck">健康检查</v-btn>
          <v-btn size="small" variant="text" @click="batchInstallAgent" :loading="batchAgentLoading">安装Agent</v-btn>
          <v-btn size="small" variant="text" @click="batchUpgradeAgent" :loading="batchAgentLoading">升级Agent</v-btn>
          <v-btn size="small" variant="text" color="error" @click="batchUninstallAgent" :loading="batchAgentLoading">卸载Agent</v-btn>
          <v-btn size="small" variant="text" color="error" @click="confirmBatchDelete">批量删除</v-btn>
          <v-btn size="small" variant="text" @click="selectedItems = []">取消选择</v-btn>
        </v-card-text>
      </v-card>

      <v-data-table-server
        :items="servers"
        :headers="headers"
        :items-length="total"
        :loading="loading"
        :page="page"
        :items-per-page="itemsPerPage"
        hover
        density="comfortable"
        item-value="id"
        show-select
        v-model="selectedItems"
        @update:page="onPageChange"
        @update:items-per-page="onItemsPerPageChange"
        @click:row="(_e: Event, { item }: { item: ServerApiItem }) => showDetail(item)"
      >
        <template #item.status="{ item }">
          <v-chip :color="statusChipColor(item.status)" size="x-small" variant="tonal" label border="sm">
            {{ statusLabel(item.status) }}
          </v-chip>
        </template>

        <template #item.name="{ item }">
          <span class="font-weight-medium">{{ item.name }}</span>
        </template>

        <template #item.address="{ item }">
          <span class="text-medium-emphasis">{{ item.domain }}:{{ item.port }}</span>
        </template>

        <template #item.category="{ item }">
          <v-chip v-if="item.category" color="primary" variant="tonal" size="small" label>
            {{ item.category }}
          </v-chip>
          <span v-else class="text-medium-emphasis">—</span>
        </template>

        <template #item.agent="{ item }">
          <span class="text-medium-emphasis">{{ item.agent_version || '—' }}</span>
        </template>

        <template #item.heartbeat="{ item }">
          <span class="text-caption text-medium-emphasis">{{ formatRelativeTime(item.last_heartbeat) }}</span>
        </template>

        <template #item.actions="{ item }">
          <div class="d-flex ga-1">
            <v-btn variant="text" size="x-small" color="primary" density="compact" @click.stop="openTerminal(item)">终端</v-btn>
            <v-btn variant="text" size="x-small" density="compact" @click.stop="openFiles(item)">文件</v-btn>
            <v-btn variant="text" size="x-small" density="compact" @click.stop="editServer(item)">编辑</v-btn>
            <v-btn variant="text" size="x-small" color="error" density="compact" @click.stop="confirmDelete(item)">删除</v-btn>
          </div>
        </template>

        <template #no-data>
          <div class="text-center text-medium-emphasis py-6">暂无服务器数据</div>
        </template>
      </v-data-table-server>
    </v-card>

    <!-- Server Detail Panel -->
    <v-expand-transition>
      <v-card v-if="detailServer" class="mt-4" elevation="0" border rounded="lg">
        <v-card-title class="d-flex align-center">
          <v-icon class="mr-2">mdi-information-outline</v-icon>
          {{ detailServer.name }}
          <v-chip :color="statusChipColor(detailServer.status)" size="small" variant="tonal" label class="ml-2">
            {{ statusLabel(detailServer.status) }}
          </v-chip>
          <v-spacer />
          <v-btn icon="mdi-close" size="small" variant="text" @click="detailServer = null" />
        </v-card-title>
        <v-divider />
        <v-tabs v-model="detailTab" density="compact">
          <v-tab value="info">系统信息</v-tab>
          <v-tab value="logs">同步日志</v-tab>
        </v-tabs>
        <v-tabs-window v-model="detailTab">
          <v-tabs-window-item value="info">
            <v-card-text>
              <v-row dense>
                <v-col cols="6" md="3">
                  <div class="text-caption text-medium-emphasis">CPU</div>
                  <div class="text-h6">{{ detailServer.system_info?.cpu_usage ?? '—' }}%</div>
                </v-col>
                <v-col cols="6" md="3">
                  <div class="text-caption text-medium-emphasis">内存</div>
                  <div class="text-h6">{{ detailServer.system_info?.mem_usage ?? '—' }}%</div>
                </v-col>
                <v-col cols="6" md="3">
                  <div class="text-caption text-medium-emphasis">磁盘</div>
                  <div class="text-h6">{{ detailServer.system_info?.disk_usage ?? '—' }}%</div>
                </v-col>
                <v-col cols="6" md="3">
                  <div class="text-caption text-medium-emphasis">Agent</div>
                  <div class="text-h6">{{ detailServer.agent_version || '未安装' }}</div>
                </v-col>
              </v-row>
            </v-card-text>
          </v-tabs-window-item>
          <v-tabs-window-item value="logs">
            <v-card-text>
              <div v-if="syncLogs.length === 0" class="text-medium-emphasis text-center py-4">暂无同步日志</div>
              <v-list v-else density="compact">
                <v-list-item v-for="log in syncLogs" :key="log.id" :subtitle="log.created_at" :title="`${log.source_path} → ${log.target_path}`">
                  <template #append>
                    <v-chip size="x-small" :color="log.status === 'success' ? 'green' : 'red'" variant="tonal" label>{{ log.status }}</v-chip>
                  </template>
                </v-list-item>
              </v-list>
            </v-card-text>
          </v-tabs-window-item>
        </v-tabs-window>
      </v-card>
    </v-expand-transition>

    <!-- Add / Edit Dialog -->
    <v-dialog v-model="showAdd" max-width="600">
      <v-card border>
        <v-card-title>{{ editing ? '编辑服务器' : '添加服务器' }}</v-card-title>
        <v-card-text>
          <v-text-field v-model="form.name" label="名称" variant="outlined" density="compact" class="mb-2" :rules="[required('服务器名称')]" />
          <v-text-field v-model="form.address" label="地址 (IP:端口)" variant="outlined" density="compact" class="mb-2" :rules="[required('地址')]" />
          <v-text-field v-model="form.category" label="分类" variant="outlined" density="compact" class="mb-2" />
          <v-select v-model="form.platform_id" :items="platforms" item-title="name" item-value="id" label="平台" variant="outlined" density="compact" class="mb-2" clearable />
          <v-text-field v-model="form.ssh_user" label="SSH 用户" variant="outlined" density="compact" class="mb-2" :rules="[required('用户名')]" />
          <v-text-field v-model="form.ssh_port" label="SSH 端口" variant="outlined" density="compact" type="number" class="mb-2" />
          <v-text-field v-model="form.password" label="密码" variant="outlined" density="compact" type="password" class="mb-2" />
          <v-select
            v-model="form.files_elevation"
            :items="filesElevationItems"
            item-title="title"
            item-value="value"
            label="文件管理提权"
            variant="outlined"
            density="compact"
            hint="非 root SSH 用户需目标机配置免密 sudo；示例见 docs/deploy/nexus-files-sudoers.example"
            persistent-hint
          />
        </v-card-text>
        <v-card-actions>
          <v-spacer />
          <v-btn variant="text" @click="showAdd = false">取消</v-btn>
          <v-btn color="primary" variant="flat" @click="saveServer" :loading="saving">保存</v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>

    <!-- Delete Confirm -->
    <v-dialog v-model="showDelete" max-width="400">
      <v-card border>
        <v-card-title>确认删除</v-card-title>
        <v-card-text>确定要删除服务器 <strong>{{ deletingServer?.name }}</strong> 吗？</v-card-text>
        <v-card-actions>
          <v-spacer />
          <v-btn variant="text" @click="showDelete = false">取消</v-btn>
          <v-btn color="error" variant="flat" @click="doDelete" :loading="deleting">删除</v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>

    <!-- Import CSV Dialog -->
    <v-dialog v-model="showImport" max-width="500">
      <v-card border>
        <v-card-title>导入服务器</v-card-title>
        <v-card-text>
          <div class="text-body-2 text-medium-emphasis mb-3">
            上传 CSV 文件批量导入服务器。
            <a href="/app/servers_import_template.csv" download class="text-primary">下载模板</a>
          </div>
          <v-file-input v-model="importFile" label="选择 CSV 文件" variant="outlined" density="compact" accept=".csv" show-size />
          <v-alert v-if="importResult" :type="importResult.failed > 0 ? 'warning' : 'success'" density="compact" variant="tonal" class="mt-3">
            成功 {{ importResult.created }}，跳过 {{ importResult.skipped }}，失败 {{ importResult.failed }}
          </v-alert>
        </v-card-text>
        <v-card-actions>
          <v-spacer />
          <v-btn variant="text" @click="showImport = false">关闭</v-btn>
          <v-btn color="primary" variant="flat" @click="doImport" :loading="importing" :disabled="!importFile?.length">开始导入</v-btn>
        </v-card-actions>
      </v-card>
    </v-dialog>
  </v-container>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { http } from '@/api'
import { useSnackbar } from '@/composables/useSnackbar'
import { useServerPagination } from '@/composables/useServerPagination'
import { statusChipColor, statusLabel, formatRelativeTime } from '@/utils/status'
import { required } from '@/utils/validation'
import type { ServerApiItem } from '@/types/api'
import { normalizeServerIds, countBatchSuccess, type BatchAgentResultItem } from '@/utils/serverSelection'
import { formatApiError } from '@/utils/apiError'

const snackbar = useSnackbar()
const router = useRouter()

// ── Paginated server list (composable) ──
const {
  servers, loading, page, itemsPerPage, total, search,
  loadServers: _load, onSearch, onPageChange, onItemsPerPageChange,
} = useServerPagination()

async function loadServers() {
  try {
    await _load()
  } catch {
    snackbar('加载服务器列表失败', 'error')
  }
}

// ── Platforms ──
const platforms = ref<{ id: number; name: string }[]>([])

// ── Dialog state ──
const showAdd = ref(false)
const showDelete = ref(false)
const editing = ref(false)
const saving = ref(false)
const deleting = ref(false)
const deletingServer = ref<ServerApiItem | null>(null)
const editingId = ref<number | null>(null)

const filesElevationItems = [
  { title: '自动（权限失败时 sudo）', value: 'auto_sudo' },
  { title: '关闭 sudo', value: 'off' },
  { title: '始终 sudo（排障）', value: 'always_sudo' },
]

const form = ref({
  name: '', address: '', category: '', platform_id: null as number | null,
  ssh_user: '', ssh_port: 22, password: '',
  files_elevation: 'auto_sudo' as 'off' | 'auto_sudo' | 'always_sudo',
})

// ── Batch selection (Vuetify returns IDs when item-value="id", objects when return-object) ──
const selectedItems = ref<Array<ServerApiItem | number>>([])
const selectedIds = computed(() => new Set(normalizeServerIds(selectedItems.value)))

// ── Detail panel ──
const detailServer = ref<ServerApiItem | null>(null)
const detailTab = ref('info')
const syncLogs = ref<{ id: number; source_path: string; target_path: string; status: string; created_at: string }[]>([])

// ── Table config ──
const headers = [
  { title: '状态', key: 'status', width: 100 },
  { title: '名称', key: 'name' },
  { title: '地址', key: 'address' },
  { title: '分类', key: 'category', width: 100 },
  { title: 'Agent', key: 'agent', width: 100 },
  { title: '心跳', key: 'heartbeat', width: 120 },
  { title: '操作', key: 'actions', width: 200, align: 'end' as const },
]

// ── Stats ──
const stats = ref([
  { label: '服务器总数', value: '0', sub: '', color: 'blue', icon: 'mdi-server-network' },
  { label: '在线', value: '0', sub: '', color: 'green', icon: 'mdi-check-circle-outline' },
  { label: '离线', value: '0', sub: '', color: 'orange', icon: 'mdi-alert-circle-outline' },
  { label: '告警中', value: '0', sub: '', color: 'red', icon: 'mdi-bell-alert-outline' },
])

// ── Data loading ──
async function loadStats() {
  try {
    const s = await http.get<{ total: number; online: number; offline: number; alerts: number }>('/servers/stats')
    stats.value[0].value = String(s.total)
    stats.value[1].value = String(s.online)
    stats.value[1].sub = s.total ? `${((s.online / s.total) * 100).toFixed(1)}% 在线率` : ''
    stats.value[2].value = String(s.offline)
    stats.value[3].value = String(s.alerts)
  } catch { /* dashboard loads without stats */ }
}

async function loadPlatforms() {
  try {
    const res = await http.get<{ items: { id: number; name: string }[] }>('/assets/platforms')
    platforms.value = res.items || []
  } catch { /* non-critical */ }
}

// ── Handlers ──
function openTerminal(item: ServerApiItem) {
  router.push({ path: '/terminal', query: { server_id: String(item.id) } })
}
function openFiles(item: ServerApiItem) {
  router.push({ path: '/files', query: { server_id: String(item.id) } })
}

// ── Batch operations ──
const batchAgentLoading = ref(false)

async function batchHealthCheck() {
  const ids = normalizeServerIds(selectedItems.value)
  if (!ids.length) return
  snackbar(`正在检查 ${ids.length} 台服务器...`)
  try {
    await http.post('/servers/check', { server_ids: ids })
    snackbar('健康检查完成')
    loadServers()
  } catch (e: unknown) { snackbar(formatApiError(e, '检查失败'), 'error') }
}

async function confirmBatchDelete() {
  if (!confirm(`确定删除选中的 ${selectedIds.value.size} 台服务器？`)) return
  for (const id of selectedIds.value) {
    try { await http.delete(`/servers/${id}`) } catch { /* skip individual errors */ }
  }
  selectedItems.value = []
  snackbar('批量删除完成')
  loadServers()
  loadStats()
}

async function batchInstallAgent() {
  const ids = normalizeServerIds(selectedItems.value)
  if (!ids.length) return
  batchAgentLoading.value = true
  try {
    const res = await http.post<{ results: BatchAgentResultItem[] }>('/servers/batch/install-agent', { server_ids: ids })
    const success = countBatchSuccess(res.results)
    snackbar(`安装完成: ${success}/${ids.length} 成功`)
    loadServers()
  } catch (e: unknown) {
    snackbar(formatApiError(e, '安装失败'), 'error')
  } finally { batchAgentLoading.value = false }
}

async function batchUpgradeAgent() {
  const ids = normalizeServerIds(selectedItems.value)
  if (!ids.length) return
  batchAgentLoading.value = true
  try {
    const res = await http.post<{ results: BatchAgentResultItem[] }>('/servers/batch/upgrade-agent', { server_ids: ids })
    const success = countBatchSuccess(res.results)
    snackbar(`升级完成: ${success}/${ids.length} 成功`)
    loadServers()
  } catch (e: unknown) {
    snackbar(formatApiError(e, '升级失败'), 'error')
  } finally { batchAgentLoading.value = false }
}

async function batchUninstallAgent() {
  const ids = normalizeServerIds(selectedItems.value)
  if (!ids.length) return
  if (!confirm(`确定卸载选中的 ${ids.length} 台服务器的 Agent？`)) return
  batchAgentLoading.value = true
  try {
    const res = await http.post<{ results: BatchAgentResultItem[] }>('/servers/batch/uninstall-agent', { server_ids: ids })
    const success = countBatchSuccess(res.results)
    snackbar(`卸载完成: ${success}/${ids.length} 成功`)
    loadServers()
  } catch (e: unknown) {
    snackbar(formatApiError(e, '卸载失败'), 'error')
  } finally { batchAgentLoading.value = false }
}

// ── CSV export ──
async function exportCSV() {
  try {
    const res = await http.getList<ServerApiItem>('/servers/', { per_page: 5000 })
    const headers = ['ID', '名称', '地址', '端口', '用户名', '分类', '状态', 'Agent版本', '最后心跳']
    const rows = (res.items || []).map(s => [
      s.id, s.name, s.domain, s.port, s.username, s.category || '', s.status,
      s.agent_version || '', s.last_heartbeat || '',
    ])
    const bom = '﻿'
    const csv = bom + [headers.join(','), ...rows.map(r => r.map(v => `"${String(v).replace(/"/g, '""')}"`).join(','))].join('\n')
    const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = `servers_${new Date().toISOString().slice(0, 10)}.csv`
    a.click()
    URL.revokeObjectURL(url)
    snackbar('导出完成')
  } catch (e: any) { snackbar(e.message || '导出失败', 'error') }
}

// ── CSV import ──
const showImport = ref(false)
const importFile = ref<File[]>([])
const importing = ref(false)
const importResult = ref<{ created: number; skipped: number; failed: number } | null>(null)

async function doImport() {
  if (!importFile.value?.length) return
  importing.value = true
  importResult.value = null
  try {
    const form = new FormData()
    form.append('file', importFile.value[0])
    const res = await http.upload<{ created: number; skipped: number; failed: number }>('/servers/import', form)
    importResult.value = res
    snackbar('导入完成')
    loadServers()
  } catch (e: unknown) {
    const msg = e instanceof Error ? e.message : '导入失败'
    snackbar(msg, 'error')
  } finally {
    importing.value = false
  }
}

// ── Server detail panel ──
async function showDetail(item: ServerApiItem) {
  detailServer.value = item
  detailTab.value = 'info'
  try {
    const res = await http.get<{ items: typeof syncLogs.value }>(`/servers/${item.id}/logs`, { limit: 20 })
    syncLogs.value = res.items || []
  } catch { syncLogs.value = [] }
}

function editServer(item: ServerApiItem) {
  editing.value = true
  editingId.value = item.id
  form.value = {
    name: item.name, address: item.domain || '', category: item.category || '',
    platform_id: item.platform_id, ssh_user: item.username || '',
    ssh_port: item.port || 22, password: '',
    files_elevation: item.files_elevation || 'auto_sudo',
  }
  showAdd.value = true
}

function confirmDelete(item: ServerApiItem) {
  deletingServer.value = item
  showDelete.value = true
}

async function saveServer() {
  saving.value = true
  try {
    const payload = {
      name: form.value.name,
      domain: form.value.address,
      username: form.value.ssh_user,
      port: form.value.ssh_port,
      category: form.value.category || undefined,
      platform_id: form.value.platform_id || undefined,
      password: form.value.password || undefined,
      files_elevation: form.value.files_elevation,
    }
    if (editing.value && editingId.value) {
      await http.put(`/servers/${editingId.value}`, payload)
    } else {
      await http.post('/servers/', payload)
    }
    showAdd.value = false
    resetForm()
    loadServers()
    loadStats()
    snackbar('保存成功')
  } catch (e: any) {
    snackbar(e.message || '保存失败', 'error')
  } finally {
    saving.value = false
  }
}

async function doDelete() {
  if (!deletingServer.value) return
  deleting.value = true
  try {
    await http.delete(`/servers/${deletingServer.value.id}`)
    showDelete.value = false
    loadServers()
    loadStats()
    snackbar('已删除')
  } catch (e: any) {
    snackbar(e.message || '删除失败', 'error')
  } finally {
    deleting.value = false
  }
}

function resetForm() {
  editing.value = false
  editingId.value = null
  form.value = {
    name: '', address: '', category: '', platform_id: null, ssh_user: '', ssh_port: 22,
    password: '', files_elevation: 'auto_sudo',
  }
}

// ── Init ──
onMounted(() => {
  loadStats()
  loadServers()
  loadPlatforms()
})
</script>
