<template>
  <div class="sg-detail-page">
    <div class="page-header">
      <div class="header-left">
        <el-button @click="goBack" link class="back-btn"><el-icon><ArrowLeft /></el-icon> 返回安全组列表</el-button>
        <el-divider direction="vertical" />
        <span class="page-title">安全组详情</span>
      </div>
      <div class="header-right">
        <el-button plain :icon="Refresh" @click="loadDetail" :loading="loading">刷新</el-button>
      </div>
    </div>

    <div class="main-content" v-loading="loading">
      <!-- 基本信息 -->
      <el-card shadow="never" class="info-card" v-if="detail">
        <template #header><span class="card-title">基本信息</span></template>
        <el-descriptions :column="2" border>
          <el-descriptions-item label="ID">{{ detail.id }}</el-descriptions-item>
          <el-descriptions-item label="名称">{{ detail.name }}</el-descriptions-item>
          <el-descriptions-item label="白名单模式">
            <div style="display: flex; align-items: center; gap: 10px">
              <el-switch :model-value="detail.drop_all" active-text="开启" inactive-text="关闭" @change="val => val ? handleEnableWhitelist() : handleDisableWhitelist()" />
              <span v-if="detail.drop_all" style="color: #e6a23c; font-size: 12px">拦截所有未放行流量</span>
            </div>
          </el-descriptions-item>
          <el-descriptions-item label="锁定" v-if="detail.lock !== undefined">
            <el-tag :type="detail.lock ? 'danger' : 'success'" size="small">{{ detail.lock ? '是' : '否' }}</el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="创建时间">{{ formatTimestamp(detail.created_at) }}</el-descriptions-item>
          <el-descriptions-item label="更新时间">{{ formatTimestamp(detail.updated_at) }}</el-descriptions-item>
        </el-descriptions>
      </el-card>

      <!-- 操作按钮 -->
      <el-card shadow="never" class="info-card" v-if="detail">
        <template #header><span class="card-title">操作</span></template>
        <div class="action-buttons" style="margin-bottom: 12px">
          <el-button type="primary" plain @click="handleEdit">修改安全组</el-button>
          <el-button type="primary" @click="handleSync">同步到宿主机</el-button>
          <el-button type="success" @click="handleBind">绑定VM</el-button>
          <el-button type="warning" @click="handleUnbind">解绑VM</el-button>
        </div>
        <el-divider style="margin: 8px 0" />
        <div class="action-buttons" style="margin-bottom: 12px">
          <el-button type="primary" plain @click="handleSetShared(true)" v-if="!detail.shared">设为共享</el-button>
          <el-button type="info" plain @click="handleSetShared(false)" v-if="detail.shared">取消共享</el-button>
          <el-button type="danger" @click="handleDelete">删除安全组</el-button>
        </div>
      </el-card>

      <!-- 规则管理 -->
      <el-card shadow="never" class="info-card">
        <template #header>
          <div class="card-header-row">
            <span class="card-title">安全组规则</span>
            <div style="display: flex; gap: 8px">
              <el-button type="primary" size="small" @click="handleApply">应用规则</el-button>
              <el-button type="primary" size="small" @click="handleAddRule">新增规则</el-button>
            </div>
          </div>
        </template>
        <el-table :data="detail?.rules || []" stripe size="small" style="width: 100%">
          <el-table-column prop="id" label="ID" width="70" />
          <el-table-column prop="protocol" label="协议" width="80">
            <template #default="{ row }"><el-tag size="small">{{ (row.protocol || '-').toUpperCase() }}</el-tag></template>
          </el-table-column>
          <el-table-column prop="action" label="动作" width="70">
            <template #default="{ row }">
              <el-tag :type="row.action === 'allow' ? 'success' : 'danger'" size="small">{{ row.action === 'allow' ? '允许' : '拒绝' }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column prop="port_range" label="端口范围" min-width="100" />
          <el-table-column prop="ip_range" label="IP 范围" min-width="110" />
          <el-table-column prop="priority" label="优先级" width="80" />
          <el-table-column prop="description" label="备注" min-width="120" />
          <el-table-column label="操作" width="120">
            <template #default="{ row }">
              <el-button link type="primary" size="small" @click="handleEditRule(row)">编辑</el-button>
              <el-button link type="danger" size="small" @click="handleDeleteRule(row)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <el-empty v-if="!detail?.rules?.length && !loading" description="暂无规则" />
      </el-card>
    </div>

    <!-- 同步弹窗 -->
    <el-dialog v-model="syncDialogVisible" title="同步到宿主机" width="420px" destroy-on-close>
      <el-form label-width="100px">
        <el-form-item label="安全组">{{ detail?.name || '-' }}</el-form-item>
        <el-form-item label="目标宿主机">
          <el-select v-model="syncHostId" 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>
      <template #footer>
        <el-button @click="syncDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="actionLoading" @click="submitSync">同步</el-button>
      </template>
    </el-dialog>

    <!-- 绑定/解绑弹窗 -->
    <el-dialog v-model="bindDialogVisible" :title="bindType === 'bind' ? '绑定安全组到虚拟机' : '解绑安全组'" width="420px" destroy-on-close>
      <el-form label-width="100px">
        <el-form-item label="安全组">{{ detail?.name || '-' }}</el-form-item>
        <el-form-item label="虚拟机">
          <div style="display: flex; gap: 8px; width: 100%">
            <el-input :model-value="bindVmId ? `${bindVmName || ''} (ID: ${bindVmId})` : ''" readonly placeholder="请选择虚拟机" style="flex: 1" />
            <el-button type="primary" @click="showVmSelector = true">选择</el-button>
          </div>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="bindDialogVisible = false">取消</el-button>
        <el-button :type="bindType === 'bind' ? 'primary' : 'warning'" :loading="actionLoading" @click="submitBind">
          {{ bindType === 'bind' ? '绑定' : '解绑' }}
        </el-button>
      </template>
    </el-dialog>

    <VmSelectorPopup v-model="showVmSelector" :service-id="serviceId" :current-id="bindVmId" @confirm="vm => { bindVmId = vm.id; bindVmName = vm.name || '' }" />

    <!-- 修改安全组弹窗 -->
    <el-dialog v-model="editDialogVisible" title="修改安全组" width="520px" destroy-on-close>
      <el-form ref="editFormRef" :model="editForm" :rules="editRules" label-width="100px">
        <el-form-item label="名称" prop="name">
          <el-input v-model="editForm.name" placeholder="安全组名称" />
        </el-form-item>
        <el-form-item label="方向" prop="direction">
          <el-select v-model="editForm.direction" placeholder="选择规则方向" style="width: 100%">
            <el-option label="入站 (in)" value="in" />
            <el-option label="出站 (out)" value="out" />
          </el-select>
        </el-form-item>
        <el-form-item label="锁定">
          <el-switch v-model="editForm.lock" active-text="用户不可修改" />
        </el-form-item>
        <el-form-item label="白名单模式">
          <el-switch v-model="editForm.drop_all" active-text="开启白名单" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="editDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="actionLoading" @click="submitEdit">确定</el-button>
      </template>
    </el-dialog>

    <!-- 规则弹窗 -->
    <el-dialog v-model="ruleDialogVisible" :title="ruleDialogType === 'add' ? '新增规则' : '编辑规则'" width="520px" destroy-on-close>
      <el-form ref="ruleFormRef" :model="ruleForm" :rules="ruleRules" label-width="100px">
        <el-form-item label="协议" prop="protocol">
          <el-select v-model="ruleForm.protocol" style="width: 100%">
            <el-option label="TCP" value="tcp" /><el-option label="UDP" value="udp" />
          </el-select>
        </el-form-item>
        <el-form-item label="动作" prop="action">
          <el-select v-model="ruleForm.action" style="width: 100%">
            <el-option label="允许" value="allow" /><el-option label="拒绝" value="deny" />
          </el-select>
        </el-form-item>
        <el-form-item label="端口范围"><el-input v-model="ruleForm.port_range" placeholder="如 80 或 80-90" /></el-form-item>
        <el-form-item label="IP 范围"><el-input v-model="ruleForm.ip_range" placeholder="如 0.0.0.0/0" /></el-form-item>
        <el-form-item label="优先级"><el-input-number v-model="ruleForm.priority" :min="0" :max="9999" style="width: 100%" /></el-form-item>
        <el-form-item label="备注"><el-input v-model="ruleForm.description" placeholder="请输入备注" /></el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="ruleDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="actionLoading" @click="submitRule">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, onActivated, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ArrowLeft, Refresh } from '@element-plus/icons-vue'
import {
  getRemoteHostList, getSecurityGroupDetail, updateSecurityGroup,
  syncSecurityGroup, bindSecurityGroup, unbindSecurityGroup,
  deleteSecurityGroup, enableSecurityGroupWhitelist, disableSecurityGroupWhitelist,
  applySecurityGroup, createSecurityGroupRule, updateSecurityGroupRule, deleteSecurityGroupRule,
  setSecurityGroupShared
} from '@/api/admin/kvmService'
import { extractApiError } from '@/utils/kvmErrorUtil'
import VmSelectorPopup from '@/components/admin/VmSelectorPopup.vue'
import { useTagsViewStore } from '@/store/tagsViewStore'

const route = useRoute()
const router = useRouter()
const tagsViewStore = useTagsViewStore()

const serviceId = computed(() => parseInt(route.query.service_id) || 0)
const serviceName = computed(() => route.query.service_name || '')
const sgId = computed(() => parseInt(route.query.sg_id) || 0)

const loading = ref(false)
const actionLoading = ref(false)
const detail = ref(null)
const hostOptions = ref([])

// 修改安全组
const editDialogVisible = ref(false)
const editFormRef = ref(null)
const editForm = reactive({ name: '', direction: '', lock: false, drop_all: false })
const editRules = {
  name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
  direction: [{ required: true, message: '请选择方向', trigger: 'change' }]
}

// 同步
const syncDialogVisible = ref(false)
const syncHostId = ref(null)

// 绑定
const bindDialogVisible = ref(false)
const bindType = ref('bind')
const bindVmId = ref(0)
const bindVmName = ref('')
const showVmSelector = ref(false)

// 规则
const ruleDialogVisible = ref(false)
const ruleDialogType = ref('add')
const ruleFormRef = ref(null)
const ruleForm = reactive({ id: undefined, group_id: 0, protocol: 'tcp', action: 'allow', port_range: '', ip_range: '', priority: 0, port_group_id: 0 })
const ruleRules = {
  protocol: [{ required: true, message: '请选择协议', trigger: 'change' }],
  action: [{ required: true, message: '请选择动作', trigger: 'change' }]
}

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 getHostLabel = (hid) => { const h = hostOptions.value.find(x => x.id === hid); return h ? h.name : (hid || '-') }

const loadHostOptions = async () => {
  try {
    const res = await getRemoteHostList({ service_id: serviceId.value, page: 1, page_size: 10})
    if (res?.data?.code === 200 && res?.data?.data) {
      const inner = res.data.data
      hostOptions.value = Array.isArray(inner) ? inner : (inner.hosts || inner.list || inner.data || [])
    }
  } catch { /* */ }
}

const loadDetail = async () => {
  if (!sgId.value) return
  loading.value = true
  try {
    const res = await getSecurityGroupDetail({ service_id: serviceId.value, id: sgId.value })
    if (res?.data?.code === 200 && res?.data?.data) {
      const inner = res.data.data
      detail.value = inner.group || inner.data || inner
    } else ElMessage.error(extractApiError(res?.data, '加载失败'))
  } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '加载失败')) } finally { loading.value = false }
}

const handleEdit = () => {
  if (!detail.value) return
  const d = detail.value
  Object.assign(editForm, { name: d.name || '', direction: d.direction || '', lock: !!d.lock, drop_all: !!d.drop_all })
  editDialogVisible.value = true
}

const submitEdit = () => {
  editFormRef.value?.validate(async (valid) => {
    if (!valid) return
    actionLoading.value = true
    try {
      const fd = new FormData()
      fd.append('service_id', serviceId.value)
      fd.append('id', sgId.value)
      fd.append('name', editForm.name)
      fd.append('direction', editForm.direction)
      fd.append('lock', editForm.lock ? 'true' : 'false')
      fd.append('drop_all', editForm.drop_all ? 'true' : 'false')
      const res = await updateSecurityGroup(fd)
      if (res?.data?.code === 200) { ElMessage.success('修改成功'); editDialogVisible.value = false; loadDetail() }
      else ElMessage.error(extractApiError(res?.data, '修改失败'))
    } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '修改失败')) } finally { actionLoading.value = false }
  })
}

const handleSync = () => { syncHostId.value = detail.value?.host_id || null; syncDialogVisible.value = true }
const submitSync = async () => {
  if (!syncHostId.value) { ElMessage.warning('请选择宿主机'); return }
  actionLoading.value = true
  try {
    const res = await syncSecurityGroup({ service_id: serviceId.value, id: sgId.value, host_id: syncHostId.value })
    if (res?.data?.code === 200) { ElMessage.success('同步成功'); syncDialogVisible.value = false; loadDetail() }
    else ElMessage.error(extractApiError(res?.data, '同步失败'))
  } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '同步失败')) } finally { actionLoading.value = false }
}

const handleBind = () => { bindType.value = 'bind'; bindVmId.value = 0; bindVmName.value = ''; bindDialogVisible.value = true }
const handleUnbind = () => { bindType.value = 'unbind'; bindVmId.value = 0; bindVmName.value = ''; bindDialogVisible.value = true }
const submitBind = async () => {
  if (!bindVmId.value) { ElMessage.warning('请选择虚拟机'); return }
  actionLoading.value = true
  try {
    const api = bindType.value === 'bind' ? bindSecurityGroup : unbindSecurityGroup
    const res = await api({ service_id: serviceId.value, id: sgId.value, vm_id: bindVmId.value })
    if (res?.data?.code === 200) { ElMessage.success(bindType.value === 'bind' ? '绑定成功' : '解绑成功'); bindDialogVisible.value = false }
    else ElMessage.error(extractApiError(res?.data, '操作失败'))
  } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '操作失败')) } finally { actionLoading.value = false }
}

const handleEnableWhitelist = () => {
  ElMessageBox.confirm('确定开启白名单模式？开启后将拦截所有未放行的流量。', '开启白名单', { type: 'warning' }).then(async () => {
    try {
      const res = await enableSecurityGroupWhitelist({ service_id: serviceId.value, id: sgId.value })
      if (res?.data?.code === 200) { ElMessage.success('开启成功'); loadDetail() }
      else ElMessage.error(extractApiError(res?.data, '开启失败'))
    } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '开启失败')) }
  }).catch(() => {})
}

const handleDisableWhitelist = () => {
  ElMessageBox.confirm('确定关闭白名单模式？', '关闭白名单', { type: 'warning' }).then(async () => {
    try {
      const res = await disableSecurityGroupWhitelist({ service_id: serviceId.value, id: sgId.value })
      if (res?.data?.code === 200) { ElMessage.success('关闭成功'); loadDetail() }
      else ElMessage.error(extractApiError(res?.data, '关闭失败'))
    } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '关闭失败')) }
  }).catch(() => {})
}

const handleApply = () => {
  ElMessageBox.confirm('确定应用安全组规则到所有绑定的虚拟机？', '应用安全组', { type: 'info' }).then(async () => {
    try {
      const res = await applySecurityGroup({ service_id: serviceId.value, id: sgId.value })
      if (res?.data?.code === 200) ElMessage.success('应用成功')
      else ElMessage.error(extractApiError(res?.data, '应用失败'))
    } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '应用失败')) }
  }).catch(() => {})
}

const handleDelete = () => {
  ElMessageBox.confirm(`确定删除安全组「${detail.value?.name}」？`, '删除确认', { type: 'warning' }).then(async () => {
    try {
      const res = await deleteSecurityGroup({ service_id: serviceId.value, id: sgId.value })
      if (res?.data?.code === 200) { ElMessage.success('删除成功'); goBack() }
      else ElMessage.error(extractApiError(res?.data, '删除失败'))
    } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '删除失败')) }
  }).catch(() => {})
}

const handleSetShared = (shared) => {
  const label = shared ? '设为共享' : '取消共享'
  ElMessageBox.confirm(`确定要${label}安全组「${detail.value?.name}」吗？`, `${label}确认`, {
    confirmButtonText: '确定', cancelButtonText: '取消', type: 'info'
  }).then(async () => {
    actionLoading.value = true
    try {
      const fd = new FormData()
      fd.append('service_id', serviceId.value)
      fd.append('id', sgId.value)
      fd.append('shared', shared ? 'true' : 'false')
      const res = await setSecurityGroupShared(fd)
      if (res?.data?.code === 200) { ElMessage.success(`${label}成功`); loadDetail() }
      else ElMessage.error(extractApiError(res?.data, `${label}失败`))
    } catch (e) { ElMessage.error(extractApiError(e?.response?.data, `${label}失败`)) } finally { actionLoading.value = false }
  }).catch(() => {})
}

const handleAddRule = () => {
  ruleDialogType.value = 'add'
  Object.assign(ruleForm, { id: undefined, group_id: sgId.value, protocol: 'tcp', action: 'allow', port_range: '', ip_range: '', priority: 0, port_group_id: 0, description: '' })
  ruleDialogVisible.value = true
}
const handleEditRule = (rule) => {
  ruleDialogType.value = 'edit'
  Object.assign(ruleForm, { id: rule.id, group_id: sgId.value, port_group_id: sgId.value, protocol: rule.protocol || 'tcp', action: rule.action || 'allow', port_range: rule.port_range || '', ip_range: rule.ip_range || '', priority: rule.priority || 0, description: rule.description || '' })
  ruleDialogVisible.value = true
}
const submitRule = () => {
  ruleFormRef.value?.validate(async (valid) => {
    if (!valid) return
    actionLoading.value = true
    try {
      const api = ruleDialogType.value === 'add' ? createSecurityGroupRule : updateSecurityGroupRule
      const res = await api({ service_id: serviceId.value, ...ruleForm })
      if (res?.data?.code === 200) { ElMessage.success('操作成功'); ruleDialogVisible.value = false; loadDetail() }
      else ElMessage.error(extractApiError(res?.data, '操作失败'))
    } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '操作失败')) } finally { actionLoading.value = false }
  })
}
const handleDeleteRule = (rule) => {
  ElMessageBox.confirm('确定删除该规则？', '删除确认', { type: 'warning' }).then(async () => {
    try {
      const res = await deleteSecurityGroupRule({ service_id: serviceId.value, id: rule.id })
      if (res?.data?.code === 200) { ElMessage.success('删除成功'); loadDetail() }
      else ElMessage.error(extractApiError(res?.data, '删除失败'))
    } catch (e) { ElMessage.error(extractApiError(e?.response?.data, '删除失败')) }
  }).catch(() => {})
}

const goBack = () => {
  tagsViewStore.delVisitedView(route)
  router.back()
  // router.push({ path: '/virtualization/kvm-service-detail', query: { service_id: serviceId.value, service_name: serviceName.value } })
}

let loadedSgId = null
const initPage = () => {
  if (!sgId.value || loadedSgId === sgId.value) return
  loadedSgId = sgId.value
  loadHostOptions()
  loadDetail()
}

watch(sgId, () => { initPage() })
onActivated(() => { if (loadedSgId !== sgId.value) initPage() })
onMounted(() => { initPage() })
</script>

<style scoped>
.sg-detail-page { padding: 0; }
.page-header { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; background: #fff; border-bottom: 1px solid #ebeef5; }
.header-left { display: flex; align-items: center; gap: 0; }
.back-btn { font-size: 14px; color: #606266; }
.back-btn:hover { color: #409eff; }
.page-title { font-size: 16px; font-weight: 600; color: #303133; }
.header-right { display: flex; gap: 8px; }
.main-content { padding: 20px; }
.info-card { margin-bottom: 20px; }
.card-title { font-weight: 600; font-size: 15px; color: #303133; }
.card-header-row { display: flex; justify-content: space-between; align-items: center; }
.action-buttons { display: flex; gap: 8px; flex-wrap: wrap; }
</style>
