<template>
  <div class="vnc-node-container">
    <div class="page-header" v-if="!embedded">
      <div class="header-left">
        <el-button @click="goBack" :icon="ArrowLeft">返回</el-button>
        <div class="header-info">
          <h3>VNC 节点管理</h3>
          <span class="sub-info" v-if="serviceName">主控服务：{{ serviceName }}</span>
        </div>
      </div>
      <div class="header-right">
        <el-button type="primary" @click="handleAdd"><el-icon><Plus /></el-icon>新增节点</el-button>
        <el-button @click="loadList"><el-icon><Refresh /></el-icon>刷新</el-button>
      </div>
    </div>

    <!-- 嵌入模式下的工具栏 -->
    <div class="embedded-toolbar" v-if="embedded">
      <el-button type="primary" @click="handleAdd"><el-icon><Plus /></el-icon>新增节点</el-button>
      <el-button @click="loadList"><el-icon><Refresh /></el-icon>刷新</el-button>
      <el-input v-model="keyword" placeholder="搜索节点" clearable style="width: 220px; margin-left: auto;" @keyup.enter="handleSearch" @clear="handleSearch">
        <template #prefix><el-icon><Search /></el-icon></template>
      </el-input>
    </div>

    <!-- 独立模式下的筛选栏 -->
    <div class="filter-bar" v-if="!embedded">
      <el-input v-model="keyword" placeholder="搜索VNC节点" clearable style="width: 220px" @keyup.enter="handleSearch" @clear="handleSearch">
        <template #prefix><el-icon><Search /></el-icon></template>
      </el-input>
    </div>

    <!-- 节点列表 -->
    <el-table :data="nodeList" v-loading="loading" stripe>
      <el-table-column prop="id" label="ID" width="70" />
      <el-table-column prop="name" label="名称" min-width="160" show-overflow-tooltip />
      <el-table-column label="地址" min-width="200">
        <template #default="{ row }">
          <span class="host-addr">{{ row.ip || '-' }}:{{ row.port || '-' }}</span>
        </template>
      </el-table-column>
      <el-table-column label="访问方案" width="110">
        <template #default="{ row }">
          <el-tag v-if="row.access_mode === 'token'" type="warning" size="small">Token传参</el-tag>
          <el-tag v-else size="small">域名解析</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="SSL" width="70">
        <template #default="{ row }">
          <el-tag v-if="row.use_ssl" type="success" size="small">是</el-tag>
          <span v-else class="text-muted">否</span>
        </template>
      </el-table-column>
      <el-table-column label="Token" min-width="140" show-overflow-tooltip>
        <template #default="{ row }">
          <span v-if="row.token" class="token-mask">{{ maskToken(row.token) }}</span>
          <span v-else class="text-muted">未设置</span>
        </template>
      </el-table-column>
      <el-table-column label="延迟" width="100">
        <template #default="{ row }">
          <span v-if="row._delay != null" :style="{ color: row._delay > 500000000 ? '#F56C6C' : row._delay > 100000000 ? '#E6A23C' : '#67C23A' }">{{ formatDelay(row._delay) }}</span>
          <span v-else class="text-muted">-</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="260" fixed="right">
        <template #default="{ row }">
          <el-button link type="primary" @click="handleEdit(row)">编辑</el-button>
          <el-button link type="success" @click="handleTest(row)">测试连接</el-button>
          <el-button link type="primary" @click="handleVmVnc(row)">VM VNC</el-button>
          <el-button link type="danger" @click="handleDelete(row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <div class="pagination-wrapper" v-if="total > 0">
      <el-pagination v-model:current-page="queryParams.page" v-model:page-size="queryParams.page_size"
        :page-sizes="[10, 20, 50]" :total="total" layout="total, sizes, prev, pager, next"
        @size-change="s => { queryParams.page_size = s; queryParams.page = 1; loadList() }"
        @current-change="p => { queryParams.page = p; loadList() }" />
    </div>

    <!-- 新增/编辑弹窗 -->
    <el-dialog v-model="formDialogVisible" :title="formType === 'add' ? '新增 VNC 节点' : '编辑 VNC 节点'" width="520px" destroy-on-close>
      <el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px">
        <el-form-item label="名称" prop="name">
          <el-input v-model="formData.name" placeholder="VNC节点名称" />
        </el-form-item>
        <el-form-item label="IP 地址" prop="ip">
          <el-input v-model="formData.ip" placeholder="如 192.168.1.100" />
        </el-form-item>
        <el-form-item label="端口" prop="port">
          <el-input v-model="formData.port" placeholder="如 6080" />
        </el-form-item>
        <el-form-item label="Token">
          <el-input v-model="formData.token" placeholder="节点鉴权Token（可选）" show-password />
        </el-form-item>
        <el-form-item label="访问方案">
          <el-select v-model="formData.access_mode" style="width: 100%">
            <el-option label="域名解析 (domain)" value="domain" />
            <el-option label="Token传参 (token)" value="token" />
          </el-select>
        </el-form-item>
        <el-form-item label="使用SSL">
          <el-switch v-model="formData.use_ssl" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="formDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="submitLoading" @click="handleSubmit">确定</el-button>
      </template>
    </el-dialog>

    <!-- 测试连接弹窗 -->
    <el-dialog v-model="testDialogVisible" title="测试 VNC 节点连接" width="460px" destroy-on-close>
      <el-form label-width="100px">
        <el-form-item label="VNC节点">{{ testTarget?.name || '-' }}</el-form-item>
        <el-form-item label="宿主机">
          <el-select v-model="testHostId" placeholder="选择宿主机" filterable style="width: 100%">
            <el-option v-for="h in hostOptions" :key="h.id" :label="`${h.name} (${h.ip || h.id})`" :value="h.id" />
          </el-select>
        </el-form-item>
      </el-form>
      <div v-if="testResult" class="test-result" :class="testResult.success ? 'success' : 'error'">
        <el-icon v-if="testResult.success"><SuccessFilled /></el-icon>
        <el-icon v-else><CircleCloseFilled /></el-icon>
        {{ testResult.message }}
      </div>
      <template #footer>
        <el-button @click="testDialogVisible = false">关闭</el-button>
        <el-button type="primary" :loading="testLoading" @click="submitTest">测试</el-button>
      </template>
    </el-dialog>

    <!-- VM VNC 弹窗 -->
    <el-dialog v-model="vmVncDialogVisible" title="获取虚拟机 VNC 连接" width="520px" destroy-on-close>
      <el-form label-width="100px">
        <el-form-item label="VNC节点">{{ vmVncTarget?.name || '-' }}</el-form-item>
        <el-form-item label="虚拟机">
          <div style="display: flex; align-items: center; gap: 8px; width: 100%">
            <el-input :model-value="vmVncVmId ? `${vmVncVmName || ''} (ID: ${vmVncVmId})` : ''" readonly placeholder="请选择虚拟机" style="flex: 1" />
            <el-button type="primary" @click="showVmVncSelector = true">选择</el-button>
          </div>
        </el-form-item>
      </el-form>
      <div v-if="vmVncResult" class="vnc-result">
        <el-descriptions :column="1" border size="small">
          <el-descriptions-item label="VNC地址">
            <el-link type="primary" :href="vmVncResult.url" target="_blank">{{ vmVncResult.url }}</el-link>
          </el-descriptions-item>
          <el-descriptions-item label="过期时间">{{ formatTimestamp(vmVncResult.expire_at) }}</el-descriptions-item>
        </el-descriptions>
      </div>
      <template #footer>
        <el-button @click="vmVncDialogVisible = false">关闭</el-button>
        <el-button type="primary" :loading="vmVncLoading" @click="submitVmVnc">获取</el-button>
      </template>
    </el-dialog>
    <!-- 虚拟机选择器 -->
    <VmSelectorPopup v-model="showVmVncSelector" :service-id="serviceId" :current-id="vmVncVmId" @confirm="handleVmVncSelected" />
  </div>
</template>

<script setup>
import { ref, reactive, computed, inject, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Refresh, Search, ArrowLeft, SuccessFilled, CircleCloseFilled } from '@element-plus/icons-vue'
import {
  getVncNodeList, getVmVnc, addVncNode, testVncNode, updateVncNode, deleteVncNode,
  getRemoteHostList
} from '@/api/admin/kvmService'
import { extractApiError } from '@/utils/kvmErrorUtil'
import VmSelectorPopup from '@/components/admin/VmSelectorPopup.vue'

const route = useRoute()
const router = useRouter()
const embedded = inject('embedded', false)
const injectedServiceId = inject('serviceId', null)
const injectedServiceName = inject('serviceName', null)
const serviceId = computed(() => injectedServiceId?.value || parseInt(route.query.service_id) || 0)
const serviceName = computed(() => injectedServiceName?.value || route.query.service_name || '')

const loading = ref(false)
const submitLoading = ref(false)
const nodeList = ref([])
const total = ref(0)
const keyword = ref('')
const hostOptions = ref([])
const queryParams = reactive({ page: 1, page_size: 10 })

const maskToken = (token) => {
  if (!token) return ''
  if (token.length <= 8) return '****'
  return token.substring(0, 4) + '****' + token.substring(token.length - 4)
}

const formatTimestamp = (ts) => {
  if (!ts) return '-'
  if (typeof ts === 'object' && ts.seconds) return new Date(Number(ts.seconds) * 1000).toLocaleString('zh-CN')
  if (typeof ts === 'string' || typeof ts === 'number') { const d = new Date(ts); return isNaN(d.getTime()) ? String(ts) : d.toLocaleString('zh-CN') }
  return '-'
}

const formatDelay = (ns) => {
  if (!ns && ns !== 0) return '-'
  const ms = ns / 1000000
  if (ms >= 1000) return (ms / 1000).toFixed(2) + ' s'
  return ms.toFixed(2) + ' ms'
}

const loadHostOptions = async () => {
  try {
    const res = await getRemoteHostList({ service_id: serviceId.value, page: 1, page_size: 10 })
    const body = res?.data
    if (body?.code === 200 && body?.data) {
      const inner = body.data
      hostOptions.value = Array.isArray(inner) ? inner : (inner.hosts || inner.list || inner.data || [])
    }
  } catch (e) { console.error('加载宿主机列表失败:', e) }
}

const loadList = async () => {
  if (!serviceId.value) return
  loading.value = true
  try {
    const params = { service_id: serviceId.value, page: queryParams.page, page_size: queryParams.page_size }
    if (keyword.value) params.keyword = keyword.value
    const res = await getVncNodeList(params)
    const body = res?.data
    if (body?.code === 200 && body?.data) {
      const inner = body.data
      nodeList.value = inner.items || inner.vnc_nodes || inner.nodes || inner.data || (Array.isArray(inner) ? inner : [])
      total.value = inner.total ?? inner.all_count ?? nodeList.value.length
    } else { nodeList.value = []; total.value = 0 }
  } catch (e) {
    console.error('获取VNC节点列表失败:', e)
    ElMessage.error('获取VNC节点列表失败')
  } finally { loading.value = false }
}

const handleSearch = () => { queryParams.page = 1; loadList() }

// 表单
const formDialogVisible = ref(false)
const formType = ref('add')
const formRef = ref(null)
const formData = reactive({ id: undefined, name: '', ip: '', port: '', token: '', access_mode: 'domain', use_ssl: false })
const formRules = {
  name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
  ip: [{ required: true, message: '请输入IP地址', trigger: 'blur' }],
  port: [{ required: true, message: '请输入端口', trigger: 'blur' }]
}

const handleAdd = () => {
  formType.value = 'add'
  Object.assign(formData, { id: undefined, name: '', ip: '', port: '', token: '', access_mode: 'domain', use_ssl: false })
  formDialogVisible.value = true
}

const handleEdit = (row) => {
  formType.value = 'edit'
  Object.assign(formData, {
    id: row.id, name: row.name || '', ip: row.ip || '', port: row.port || '', token: row.token || '',
    access_mode: row.access_mode || 'domain', use_ssl: !!row.use_ssl
  })
  formDialogVisible.value = true
}

const handleSubmit = () => {
  formRef.value?.validate(async (valid) => {
    if (!valid) return
    submitLoading.value = true
    try {
      let res
      const payload = { service_id: serviceId.value, name: formData.name, ip: formData.ip, port: formData.port, token: formData.token, access_mode: formData.access_mode, use_ssl: formData.use_ssl }
      if (formType.value === 'add') {
        res = await addVncNode(payload)
      } else {
        payload.id = formData.id
        res = await updateVncNode(payload)
      }
      if (res?.data?.code === 200) {
        ElMessage.success(formType.value === 'add' ? '创建成功' : '修改成功')
        formDialogVisible.value = false
        loadList()
      } else ElMessage.error(extractApiError(res?.data, '操作失败'))
    } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '操作失败')) } finally { submitLoading.value = false }
  })
}

const handleDelete = (row) => {
  ElMessageBox.confirm(`确定要删除VNC节点「${row.name}」吗？`, '删除确认', {
    confirmButtonText: '确定删除', cancelButtonText: '取消', type: 'warning'
  }).then(async () => {
    try {
      const res = await deleteVncNode({ service_id: serviceId.value, id: row.id })
      if (res?.data?.code === 200) { ElMessage.success('删除成功'); loadList() }
      else ElMessage.error(extractApiError(res?.data, '删除失败'))
    } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '删除失败')) }
  }).catch(() => {})
}

// 测试连接
const testDialogVisible = ref(false)
const testTarget = ref(null)
const testHostId = ref(null)
const testLoading = ref(false)
const testResult = ref(null)

const handleTest = (row) => {
  testTarget.value = row
  testHostId.value = null
  testResult.value = null
  testDialogVisible.value = true
}

const submitTest = async () => {
  if (!testHostId.value) { ElMessage.warning('请选择宿主机'); return }
  testLoading.value = true
  testResult.value = null
  try {
    const res = await testVncNode({ service_id: serviceId.value, id: testTarget.value.id, host_id: testHostId.value })
    if (res?.data?.code === 200) {
      const d = res.data.data || {}
      const delay = d.delay
      if (delay != null && testTarget.value) {
        const idx = nodeList.value.findIndex(n => n.id === testTarget.value.id)
        if (idx >= 0) nodeList.value[idx]._delay = delay
      }
      testResult.value = { success: true, message: '连接测试成功' + (delay != null ? `，延迟：${formatDelay(delay)}` : '') }
    } else {
      testResult.value = { success: false, message: extractApiError(res?.data, '连接测试失败') }
    }
  } catch (e) {
    testResult.value = { success: false, message: '连接测试异常: ' + (e?.message || '未知错误') }
  } finally { testLoading.value = false }
}

// VM VNC
const vmVncDialogVisible = ref(false)
const vmVncTarget = ref(null)
const vmVncVmId = ref(0)
const vmVncVmName = ref('')
const vmVncLoading = ref(false)
const vmVncResult = ref(null)
const showVmVncSelector = ref(false)
const handleVmVncSelected = (vm) => { vmVncVmId.value = vm.id; vmVncVmName.value = vm.name || '' }

const handleVmVnc = (row) => {
  vmVncTarget.value = row
  vmVncVmId.value = 0
  vmVncVmName.value = ''
  vmVncResult.value = null
  vmVncDialogVisible.value = true
}

const submitVmVnc = async () => {
  if (!vmVncVmId.value) { ElMessage.warning('请选择虚拟机'); return }
  vmVncLoading.value = true
  vmVncResult.value = null
  try {
    const res = await getVmVnc({ service_id: serviceId.value, id: vmVncTarget.value.id, vm_id: vmVncVmId.value })
    if (res?.data?.code === 200 && res?.data?.data) {
      vmVncResult.value = res.data.data
    } else {
      ElMessage.error(extractApiError(res?.data, '获取VNC连接信息失败'))
    }
  } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '获取VNC连接信息失败')) } finally { vmVncLoading.value = false }
}

const goBack = () => { router.push('/virtualization/kvm-service') }

onMounted(async () => {
  if (serviceId.value) {
    await loadHostOptions()
    loadList()
  }
})
</script>

<style scoped>
.vnc-node-container { padding: 20px; }
.host-addr { font-family: 'Consolas', 'Monaco', monospace; color: #409eff; font-size: 13px; }
.token-mask { font-family: 'Consolas', 'Monaco', monospace; color: #909399; font-size: 13px; }
.test-result { display: flex; align-items: center; gap: 8px; padding: 12px; border-radius: 4px; margin-top: 12px; font-size: 14px; }
.test-result.success { background: #f0f9eb; color: #67c23a; }
.test-result.error { background: #fef0f0; color: #f56c6c; }
.vnc-result { margin-top: 12px; }
</style>
