<template>
  <div class="host-group-mapping-container">
    <!-- 顶部信息 -->
    <div class="page-header" v-if="!embedded">
      <div class="header-left">
        <div class="header-info">
          <h3>宿主机组映射管理</h3>
        </div>
      </div>
      <div class="header-right">
        <el-button @click="loadAllServices" :loading="servicesLoading">
          <el-icon><Refresh /></el-icon>刷新
        </el-button>
      </div>
    </div>
    <div class="embedded-toolbar" v-if="embedded">
      <el-button type="primary" @click="handleSync(embeddedServiceId)" :loading="syncLoadingMap[embeddedServiceId]"><el-icon><RefreshRight /></el-icon>从远程同步</el-button>
      <el-button @click="loadHostGroupsForService(embeddedServiceId)"><el-icon><Refresh /></el-icon>刷新</el-button>
    </div>

    <!-- embedded 模式：直接展示单个主控的主机组 -->
    <div v-if="embedded" class="main-panel">
      <div class="panel-header">
        <h4>本地主机组列表</h4>
      </div>
      <div class="panel-body" v-loading="hostGroupLoadingMap[embeddedServiceId]">
        <el-table :data="getTreeGroupList(embeddedServiceId)" stripe style="width: 100%" row-key="_rowKey"
          default-expand-all :tree-props="{ children: '_children', hasChildren: '_hasChildren' }">
          <el-table-column prop="name" label="名称" min-width="140" show-overflow-tooltip />
          <el-table-column prop="id" label="ID" width="70" />
          <el-table-column label="远程ID" width="80">
            <template #default="{ row }">{{ row.remoteId || '-' }}</template>
          </el-table-column>
          <el-table-column label="父级远程ID" width="100">
            <template #default="{ row }">{{ row.parentRemoteId || '-' }}</template>
          </el-table-column>
          <el-table-column label="绑定商品组" min-width="120">
            <template #default="{ row }">
              <el-tag v-if="row.goodGroupId" type="success" size="small">商品组#{{ row.goodGroupId }}</el-tag>
              <span v-else class="text-muted">未绑定</span>
            </template>
          </el-table-column>
          <el-table-column label="绑定商品" min-width="100">
            <template #default="{ row }">
              <el-tag v-if="row.goodId" type="warning" size="small">商品#{{ row.goodId }}</el-tag>
              <span v-else class="text-muted">未绑定</span>
            </template>
          </el-table-column>
          <el-table-column prop="note" label="备注" min-width="120" show-overflow-tooltip>
            <template #default="{ row }">{{ row.note || '-' }}</template>
          </el-table-column>
          <el-table-column label="操作" width="260" fixed="right">
            <template #default="{ row }">
              <el-button link type="primary" size="small" @click.stop="handleEditGroup(row)">编辑</el-button>
              <el-button link type="primary" size="small" @click.stop="handleBind(row)">绑定</el-button>
              <el-button link type="success" size="small" @click.stop="handleGenerateGoods(row)">生成商品</el-button>
              <el-button link type="danger" size="small" @click.stop="handleDeleteGroup(row, embeddedServiceId)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>

    <!-- 非 embedded 模式：展示所有主控服务，每个可折叠展开 -->
    <div v-if="!embedded" v-loading="servicesLoading">
      <el-empty v-if="!servicesLoading && serviceList.length === 0" description="暂无主控服务" :image-size="100" />
      <div v-for="service in serviceList" :key="service.id" class="service-card">
        <div class="service-card-header" @click="toggleService(service)">
          <div class="service-card-title">
            <el-icon class="expand-icon" :class="{ 'is-expanded': expandedServiceIds.has(service.id) }"><ArrowRight /></el-icon>
            <span class="service-name">{{ service.name }}</span>
            <el-tag size="small" type="info">ID: {{ service.id }}</el-tag>
            <el-tag v-if="service.host" size="small">{{ service.host }}{{ service.port ? ':' + service.port : '' }}</el-tag>
          </div>
          <div class="service-card-actions" @click.stop>
            <el-button type="primary" size="small" @click="handleSync(service.id)" :loading="syncLoadingMap[service.id]">
              <el-icon><RefreshRight /></el-icon>同步
            </el-button>
            <el-button size="small" @click="loadHostGroupsForService(service.id)">
              <el-icon><Refresh /></el-icon>刷新
            </el-button>
          </div>
        </div>
        <el-collapse-transition>
          <div v-show="expandedServiceIds.has(service.id)" class="service-card-body">
            <div v-loading="hostGroupLoadingMap[service.id]" class="host-group-table-wrapper">
              <el-table
                v-if="hostGroupDataMap[service.id]?.length > 0"
                :data="getTreeGroupList(service.id)"
                stripe style="width: 100%" row-key="_rowKey"
                default-expand-all
                :tree-props="{ children: '_children', hasChildren: '_hasChildren' }"
              >
                <el-table-column prop="name" label="名称" min-width="140" show-overflow-tooltip />
                <el-table-column prop="id" label="ID" width="70" />
                <el-table-column label="远程ID" width="80">
                  <template #default="{ row }">{{ row.remoteId || '-' }}</template>
                </el-table-column>
                <el-table-column label="父级远程ID" width="100">
                  <template #default="{ row }">{{ row.parentRemoteId || '-' }}</template>
                </el-table-column>
                <el-table-column label="绑定商品组" min-width="120">
                  <template #default="{ row }">
                    <el-tag v-if="row.goodGroupId" type="success" size="small">商品组#{{ row.goodGroupId }}</el-tag>
                    <span v-else class="text-muted">未绑定</span>
                  </template>
                </el-table-column>
                <el-table-column label="绑定商品" min-width="100">
                  <template #default="{ row }">
                    <el-tag v-if="row.goodId" type="warning" size="small">商品#{{ row.goodId }}</el-tag>
                    <span v-else class="text-muted">未绑定</span>
                  </template>
                </el-table-column>
                <el-table-column prop="note" label="备注" min-width="120" show-overflow-tooltip>
                  <template #default="{ row }">{{ row.note || '-' }}</template>
                </el-table-column>
                <el-table-column label="操作" width="260" fixed="right">
                  <template #default="{ row }">
                    <el-button link type="primary" size="small" @click.stop="handleEditGroup(row)">编辑</el-button>
                    <el-button link type="primary" size="small" @click.stop="handleBind(row)">绑定</el-button>
                    <el-button link type="success" size="small" @click.stop="handleGenerateGoods(row)">生成商品</el-button>
                    <el-button link type="danger" size="small" @click.stop="handleDeleteGroup(row, service.id)">删除</el-button>
                  </template>
                </el-table-column>
              </el-table>
              <el-empty v-else-if="!hostGroupLoadingMap[service.id]" description="暂无主机组数据，请先从远程同步" :image-size="60" />
            </div>
          </div>
        </el-collapse-transition>
      </div>
    </div>

    <!-- 编辑本地主机组弹窗 -->
    <el-dialog v-model="editDialogVisible" title="编辑本地主机组" width="480px" destroy-on-close>
      <el-form ref="editFormRef" :model="editForm" :rules="editFormRules" label-width="90px">
        <el-form-item label="名称" prop="name">
          <el-input v-model="editForm.name" placeholder="请输入名称" />
        </el-form-item>
        <el-form-item label="备注" prop="note">
          <el-input v-model="editForm.note" type="textarea" :rows="3" placeholder="备注（可选）" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="editDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="editSubmitLoading" @click="submitEdit">保存</el-button>
      </template>
    </el-dialog>

    <!-- 绑定弹窗 -->
    <el-dialog v-model="bindDialogVisible" title="绑定商品组/商品" width="520px" destroy-on-close>
      <el-form ref="bindFormRef" :model="bindForm" label-width="100px">
        <el-form-item label="主机组">
          <el-input :model-value="bindForm._name" disabled />
        </el-form-item>
        <el-form-item label="绑定商品组">
          <div class="bind-selector-row">
            <el-input
              :model-value="bindForm.good_group_id ? `商品组 #${bindForm.good_group_id}${bindForm._groupName ? ' - ' + bindForm._groupName : ''}` : '未绑定'"
              disabled
              style="flex: 1"
            />
            <el-button type="primary" @click="showGroupSelector = true" style="margin-left: 8px" :disabled="!!bindForm.good_id">选择</el-button>
            <el-button v-if="bindForm.good_group_id" @click="clearBindGroup" style="margin-left: 4px">清除</el-button>
          </div>
          <div v-if="bindForm.good_id" style="font-size: 12px; color: #e6a23c; margin-top: 4px">已绑定商品，请先清除商品后再绑定商品组</div>
        </el-form-item>
        <el-form-item label="绑定商品">
          <div class="bind-selector-row">
            <el-input
              :model-value="bindForm.good_id ? `商品 #${bindForm.good_id}${bindForm._goodName ? ' - ' + bindForm._goodName : ''}` : '未绑定'"
              disabled
              style="flex: 1"
            />
            <el-button type="primary" @click="showProductSelector = true" style="margin-left: 8px" :disabled="!!bindForm.good_group_id">选择</el-button>
            <el-button v-if="bindForm.good_id" @click="clearBindProduct" style="margin-left: 4px">清除</el-button>
          </div>
          <div v-if="bindForm.good_group_id" style="font-size: 12px; color: #e6a23c; margin-top: 4px">已绑定商品组，请先清除商品组后再绑定商品</div>
        </el-form-item>
        <el-alert type="info" :closable="false" style="margin-bottom: 12px;">
          <template #title>
            可选择绑定商品组或商品（选择其中一个即可），点击"清除"按钮可取消对应绑定。
          </template>
        </el-alert>
      </el-form>
      <template #footer>
        <el-button @click="bindDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="bindSubmitLoading" @click="submitBind">绑定</el-button>
      </template>
    </el-dialog>

    <!-- 生成商品 - 父级商品组选择器 -->
    <ProductGroupSelector
      v-model="showGenerateGroupSelector"
      :current-group-id="generateForm.parent_group_id"
      @confirm="g => { generateForm.parent_group_id = g.id; generateForm._parentGroupName = g.name }"
    />

    <!-- 生成商品 - 标签选择器 -->
    <el-dialog v-model="showGenerateTagSelector" title="选择标签" width="560px" append-to-body destroy-on-close>
      <div style="margin-bottom: 12px; display: flex; gap: 8px">
        <el-input v-model="tagKeyword" placeholder="搜索标签名称" clearable style="width: 220px" @input="filterTags">
          <template #prefix><el-icon><Search /></el-icon></template>
        </el-input>
        <el-button :icon="Refresh" @click="() => { tagOptions.value = []; fetchTagOptions() }" :loading="tagLoading">刷新</el-button>
      </div>
      <el-table :data="filteredTagOptions" v-loading="tagLoading" highlight-current-row
        @current-change="row => selectedTagRow = row" :height="300" stripe size="small">
        <el-table-column prop="id" label="ID" width="70" />
        <el-table-column prop="name" label="名称" min-width="160" show-overflow-tooltip />
      </el-table>
      <el-empty v-if="!filteredTagOptions.length && !tagLoading" description="暂无标签" :image-size="60" />
      <template #footer>
        <el-button @click="showGenerateTagSelector = false">取消</el-button>
        <el-button type="primary" :disabled="!selectedTagRow" @click="confirmTagSelect">确定选择</el-button>
      </template>
    </el-dialog>

    <!-- 绑定弹窗用商品组选择器 -->
    <ProductGroupSelector
      v-model="showGroupSelector"
      :current-group-id="bindForm.good_group_id"
      @confirm="handleGroupSelected"
    />

    <!-- 商品选择器 -->
    <ProductSelector
      v-model="showProductSelector"
      :current-product-id="bindForm.good_id"
      @confirm="handleProductSelected"
    />

    <!-- 生成商品弹窗 -->
    <el-dialog v-model="generateDialogVisible" title="根据主机组自动生成商品" width="520px" destroy-on-close>
      <el-alert type="warning" :closable="false" style="margin-bottom: 16px;">
        <template #title>
          此操作将根据所选主机组树自动生成 GoodGroup（商品分组）、Goods（商品）和 Args（参数），请谨慎操作。
        </template>
      </el-alert>
      <el-form ref="generateFormRef" :model="generateForm" :rules="generateFormRules" label-width="120px">
        <el-form-item label="起始主机组ID" prop="id">
          <el-input :model-value="generateForm.id" disabled style="width: 100%" />
        </el-form-item>
        <el-form-item label="父级GoodGroup">
          <div class="bind-selector-row">
            <el-input
              :model-value="generateForm.parent_group_id ? `商品组 #${generateForm.parent_group_id}${generateForm._parentGroupName ? ' - ' + generateForm._parentGroupName : ''}` : '不挂载父级'"
              disabled
              style="flex: 1"
            />
            <el-button type="primary" @click="showGenerateGroupSelector = true" style="margin-left: 8px">选择</el-button>
            <el-button v-if="generateForm.parent_group_id" @click="generateForm.parent_group_id = 0; generateForm._parentGroupName = ''" style="margin-left: 4px">清除</el-button>
          </div>
        </el-form-item>
        <el-form-item label="标签">
          <div class="bind-selector-row">
            <el-input
              :model-value="generateForm.tag_id ? `标签 #${generateForm.tag_id}${generateForm._tagName ? ' - ' + generateForm._tagName : ''}` : '不设置标签'"
              disabled
              style="flex: 1"
            />
            <el-button type="primary" @click="showGenerateTagSelector = true" style="margin-left: 8px">选择</el-button>
            <el-button v-if="generateForm.tag_id" @click="generateForm.tag_id = 0; generateForm._tagName = ''" style="margin-left: 4px">清除</el-button>
          </div>
        </el-form-item>
        <el-form-item label="Table标识" prop="table">
          <el-input v-model="generateForm.table" placeholder="如 kvm_service" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="generateDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="generateSubmitLoading" @click="submitGenerate">确定生成</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, computed, inject, onMounted, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Refresh, RefreshRight, Search, ArrowLeft, ArrowRight } from '@element-plus/icons-vue'
import {
  getHostGroupList,
  syncHostGroup,
  bindHostGroup,
  updateHostGroup,
  generateGoodsByHostGroup,
  deleteHostGroup,
  getKvmServiceList
} from '@/api/admin/kvmService'
import { extractApiError } from '@/utils/kvmErrorUtil'
import { getProductGroupTagList } from '@/api/admin/product'
import ProductGroupSelector from '@/components/admin/ProductGroupSelector.vue'
import ProductSelector from '@/components/admin/ProductSelector.vue'
import dayjs from 'dayjs'

const route = useRoute()
const router = useRouter()
const embedded = inject('embedded', false)
const injectedServiceId = inject('serviceId', null)
const injectedServiceName = inject('serviceName', null)

const embeddedServiceId = computed(() => injectedServiceId?.value || 0)

// ==================== 主控服务列表 ====================
const serviceList = ref([])
const servicesLoading = ref(false)
const expandedServiceIds = reactive(new Set())

const normalizeService = (s) => ({
  id: s.Id ?? s.id,
  name: s.Name ?? s.name,
  host: s.Host ?? s.host,
  port: s.Port ?? s.port,
  note: s.Note ?? s.note
})

const loadAllServices = async () => {
  servicesLoading.value = true
  try {
    const res = await getKvmServiceList({ page: 1, count: 100, key: '' })
    if (res?.data?.code === 200 && res?.data?.data) {
      const inner = res.data.data
      const raw = inner.data || inner.list || (Array.isArray(inner) ? inner : [])
      serviceList.value = raw.map(normalizeService)
      serviceList.value.forEach(s => {
        expandedServiceIds.add(s.id)
        loadHostGroupsForService(s.id)
      })
    }
  } catch { /* */ } finally {
    servicesLoading.value = false
  }
}

// ==================== 每个主控下的主机组数据 ====================
const hostGroupDataMap = reactive({})
const hostGroupLoadingMap = reactive({})
const syncLoadingMap = reactive({})

const normalizeHostGroup = (item) => {
  if (!item) return item
  return {
    ...item,
    id: item.Id ?? item.id,
    serviceId: item.ServiceId ?? item.serviceId ?? item.service_id,
    remoteId: item.ServiceHostGroupId ?? item.serviceHostGroupId ?? item.remoteId ?? item.remote_id,
    parentRemoteId: item.ServiceParentHostGroupId ?? item.serviceParentHostGroupId ?? item.parentRemoteId ?? item.parent_remote_id ?? 0,
    goodGroupId: item.GoodGroupId ?? item.goodGroupId ?? item.good_group_id ?? 0,
    goodId: item.GoodId ?? item.goodId ?? item.good_id ?? 0,
    name: item.Name ?? item.name,
    note: item.Note ?? item.note,
    CreatedAt: item.CreatedAt ?? item.createdAt ?? item.created_at,
    UpdatedAt: item.UpdatedAt ?? item.updatedAt ?? item.updated_at,
  }
}

const loadHostGroupsForService = async (svcId) => {
  if (!svcId) return
  hostGroupLoadingMap[svcId] = true
  try {
    const res = await getHostGroupList({ service_id: svcId })
    const body = res?.data
    if (body?.code === 200 && body?.data) {
      const items = Array.isArray(body.data) ? body.data : (body.data.data || body.data.list || [])
      hostGroupDataMap[svcId] = items.map(normalizeHostGroup)
    } else {
      hostGroupDataMap[svcId] = []
      if (body?.message) ElMessage.warning(body.message)
    }
  } catch (error) {
    console.error('获取本地主机组列表失败:', error)
    ElMessage.error('获取本地主机组列表失败')
    hostGroupDataMap[svcId] = []
  } finally {
    hostGroupLoadingMap[svcId] = false
  }
}

const buildTree = (items) => {
  if (!items || !items.length) return []
  const map = new Map()
  items.forEach(item => {
    map.set(item.remoteId, { ...item, _rowKey: `g-${item.id}`, _children: [], _hasChildren: false })
  })
  const roots = []
  map.forEach(item => {
    if (item.parentRemoteId && map.has(item.parentRemoteId)) {
      const parent = map.get(item.parentRemoteId)
      parent._children.push(item)
      parent._hasChildren = true
    } else {
      roots.push(item)
    }
  })
  return roots
}

const getTreeGroupList = (svcId) => {
  return buildTree(hostGroupDataMap[svcId] || [])
}

const toggleService = (service) => {
  if (expandedServiceIds.has(service.id)) {
    expandedServiceIds.delete(service.id)
  } else {
    expandedServiceIds.add(service.id)
    if (!hostGroupDataMap[service.id]) {
      loadHostGroupsForService(service.id)
    }
  }
}

// ==================== 同步 ====================
const handleSync = async (svcId) => {
  if (!svcId) {
    ElMessage.warning('缺少主控服务ID')
    return
  }
  ElMessageBox.confirm('确定要从远程同步主机组数据到本地吗？', '同步确认', {
    confirmButtonText: '确定同步',
    cancelButtonText: '取消',
    type: 'info'
  }).then(async () => {
    syncLoadingMap[svcId] = true
    try {
      const res = await syncHostGroup({ service_id: svcId })
      const body = res?.data
      if (body?.code === 200) {
        const synced = body.data
        const count = Array.isArray(synced) ? synced.length : 0
        ElMessage.success(`同步完成，共同步 ${count} 个主机组`)
      } else {
        ElMessage.warning(body?.message || '同步返回异常')
      }
      loadHostGroupsForService(svcId)
    } catch (error) {
      ElMessage.error(extractApiError(error?.response?.data, '同步失败'))
    } finally {
      syncLoadingMap[svcId] = false
    }
  }).catch(() => {})
}

// ==================== 编辑 ====================
const editDialogVisible = ref(false)
const editSubmitLoading = ref(false)
const editFormRef = ref(null)
const editingServiceId = ref(null)

const editForm = reactive({
  id: undefined,
  name: '',
  note: ''
})

const editFormRules = {
  name: [{ required: true, message: '请输入名称', trigger: 'blur' }]
}

const handleEditGroup = (row) => {
  editingServiceId.value = row.serviceId
  Object.assign(editForm, {
    id: Number(row.Id ?? row.id),
    name: row.Name ?? row.name,
    note: row.Note ?? row.note ?? ''
  })
  editDialogVisible.value = true
}

const submitEdit = () => {
  editFormRef.value?.validate(async (valid) => {
    if (!valid) return
    editSubmitLoading.value = true
    try {
      const res = await updateHostGroup({
        id: editForm.id,
        name: editForm.name,
        note: editForm.note
      })
      const body = res?.data
      if (body?.code === 200) {
        ElMessage.success('修改成功')
        editDialogVisible.value = false
        if (editingServiceId.value) loadHostGroupsForService(editingServiceId.value)
      } else {
        ElMessage.error(extractApiError(body, '修改失败'))
      }
    } catch (error) {
      ElMessage.error(extractApiError(error?.response?.data, '修改失败'))
    } finally {
      editSubmitLoading.value = false
    }
  })
}

// ==================== 绑定 ====================
const bindDialogVisible = ref(false)
const bindSubmitLoading = ref(false)
const bindFormRef = ref(null)
const bindingServiceId = ref(null)

const bindForm = reactive({
  id: undefined,
  _name: '',
  _groupName: '',
  _goodName: '',
  good_group_id: 0,
  good_id: 0
})

const showGroupSelector = ref(false)
const showProductSelector = ref(false)

const handleGroupSelected = (group) => {
  bindForm.good_group_id = group.id
  bindForm._groupName = group.name || ''
}

const handleProductSelected = (product) => {
  bindForm.good_id = product.id
  bindForm._goodName = product.name || ''
}

const clearBindGroup = () => {
  bindForm.good_group_id = 0
  bindForm._groupName = ''
}

const clearBindProduct = () => {
  bindForm.good_id = 0
  bindForm._goodName = ''
}

const handleBind = (row) => {
  bindingServiceId.value = row.serviceId
  Object.assign(bindForm, {
    id: Number(row.Id ?? row.id),
    _name: row.Name ?? row.name,
    _groupName: '',
    _goodName: '',
    good_group_id: row.goodGroupId ?? row.GoodGroupId ?? 0,
    good_id: row.goodId ?? row.GoodId ?? 0
  })
  bindDialogVisible.value = true
}

const submitBind = async () => {
  bindSubmitLoading.value = true
  try {
    const res = await bindHostGroup({
      id: bindForm.id,
      good_group_id: bindForm.good_group_id,
      good_id: bindForm.good_id
    })
    const body = res?.data
    if (body?.code === 200) {
      ElMessage.success('绑定成功')
      bindDialogVisible.value = false
      if (bindingServiceId.value) loadHostGroupsForService(bindingServiceId.value)
    } else {
      ElMessage.error(extractApiError(body, '绑定失败'))
    }
  } catch (error) {
    ElMessage.error(extractApiError(error?.response?.data, '绑定失败'))
  } finally {
    bindSubmitLoading.value = false
  }
}

// ==================== 生成商品 ====================
const generateDialogVisible = ref(false)
const generateSubmitLoading = ref(false)
const generateFormRef = ref(null)
const generatingServiceId = ref(null)

const generateForm = reactive({
  id: undefined,
  parent_group_id: 0,
  _parentGroupName: '',
  tag_id: 0,
  _tagName: '',
  table: 'kvm_service'
})

const generateFormRules = {
  id: [{ required: true, message: '主机组ID不能为空', trigger: 'blur' }]
}

const showGenerateGroupSelector = ref(false)

const showGenerateTagSelector = ref(false)
const tagOptions = ref([])
const tagLoading = ref(false)
const tagKeyword = ref('')
const selectedTagRow = ref(null)
const filteredTagOptions = computed(() =>
  tagKeyword.value
    ? tagOptions.value.filter(t => t.name?.includes(tagKeyword.value))
    : tagOptions.value
)
const filterTags = () => { /* computed 自动响应 */ }
const confirmTagSelect = () => {
  if (!selectedTagRow.value) return
  generateForm.tag_id = selectedTagRow.value.id
  generateForm._tagName = selectedTagRow.value.name
  showGenerateTagSelector.value = false
  selectedTagRow.value = null
  tagKeyword.value = ''
}

const loadTagOptions = async () => {
  if (tagOptions.value.length) return
  await fetchTagOptions()
}

const fetchTagOptions = async () => {
  tagLoading.value = true
  try {
    const res = await getProductGroupTagList()
    if (res?.data?.code === 200 && res?.data?.data) {
      const inner = res.data.data
      tagOptions.value = Array.isArray(inner) ? inner : (inner.data || inner.list || [])
    }
  } catch { /* */ } finally { tagLoading.value = false }
}

watch(showGenerateTagSelector, (val) => { if (val) loadTagOptions() })

const handleGenerateGoods = (row) => {
  generatingServiceId.value = row.serviceId
  Object.assign(generateForm, {
    id: Number(row.Id ?? row.id),
    parent_group_id: 0,
    _parentGroupName: '',
    tag_id: 0,
    _tagName: '',
    table: 'kvm_service'
  })
  generateDialogVisible.value = true
}

const submitGenerate = () => {
  generateFormRef.value?.validate(async (valid) => {
    if (!valid) return

    ElMessageBox.confirm('此操作会自动生成商品分组和商品，确定继续吗？', '确认生成', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(async () => {
      generateSubmitLoading.value = true
      try {
        const payload = { id: generateForm.id }
        if (generateForm.parent_group_id) payload.parent_group_id = generateForm.parent_group_id
        if (generateForm.tag_id) payload.tag_id = generateForm.tag_id
        if (generateForm.table) payload.table = generateForm.table

        const res = await generateGoodsByHostGroup(payload)
        const body = res?.data
        if (body?.code === 200) {
          ElMessage.success('商品生成成功')
          generateDialogVisible.value = false
          if (generatingServiceId.value) loadHostGroupsForService(generatingServiceId.value)
        } else {
          ElMessage.error(extractApiError(body, '商品生成失败'))
        }
      } catch (error) {
        ElMessage.error(extractApiError(error?.response?.data, '生成失败'))
      } finally {
        generateSubmitLoading.value = false
      }
    }).catch(() => {})
  })
}

// ==================== 删除本地主机组 ====================
const handleDeleteGroup = (row, svcId) => {
  const rawId = Number(row.Id ?? row.id)
  if (!rawId) {
    ElMessage.error('无法获取主机组ID')
    return
  }
  ElMessageBox.confirm(`确定要删除本地主机组「${row.Name ?? row.name}」吗？删除后不可恢复。`, '删除确认', {
    confirmButtonText: '确定删除',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(async () => {
    try {
      const res = await deleteHostGroup({ id: rawId })
      const body = res?.data
      if (body?.code === 200) {
        ElMessage.success('删除成功')
        if (svcId) loadHostGroupsForService(svcId)
      } else {
        ElMessage.error(extractApiError(body, '删除失败'))
      }
    } catch (error) {
      ElMessage.error(extractApiError(error?.response?.data, '删除失败'))
    }
  }).catch(() => {})
}

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

onMounted(() => {
  if (!embedded) {
    loadAllServices()
  } else if (embeddedServiceId.value) {
    loadHostGroupsForService(embeddedServiceId.value)
  }
})
</script>

<style scoped>
.host-group-mapping-container {
  padding: 20px;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  padding-bottom: 16px;
  border-bottom: 1px solid #ebeef5;
}

.header-left {
  display: flex;
  align-items: center;
  gap: 16px;
}

.header-info h3 {
  margin: 0;
  font-size: 18px;
  color: #303133;
}

.sub-info {
  font-size: 13px;
  color: #909399;
}

.header-right {
  display: flex;
  gap: 8px;
}

.embedded-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 16px;
}

.main-panel {
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
  overflow: hidden;
}

.panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 20px;
  border-bottom: 1px solid #ebeef5;
  background: #fafafa;
}

.panel-header h4 {
  margin: 0;
  font-size: 15px;
  color: #303133;
}

.panel-body {
  padding: 16px;
  min-height: 200px;
}

/* 主控服务卡片 */
.service-card {
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
  margin-bottom: 12px;
  overflow: hidden;
  border: 1px solid #ebeef5;
  transition: border-color 0.2s;
}
.service-card:hover {
  border-color: #c0c4cc;
}

.service-card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 20px;
  cursor: pointer;
  user-select: none;
  background: #fafbfc;
  transition: background 0.2s;
}
.service-card-header:hover {
  background: #f0f2f5;
}

.service-card-title {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  min-width: 0;
}

.expand-icon {
  font-size: 14px;
  color: #909399;
  transition: transform 0.3s;
  flex-shrink: 0;
}
.expand-icon.is-expanded {
  transform: rotate(90deg);
}

.service-name {
  font-size: 15px;
  font-weight: 600;
  color: #303133;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.service-card-actions {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}

.service-card-body {
  border-top: 1px solid #ebeef5;
}

.host-group-table-wrapper {
  padding: 16px;
  min-height: 100px;
}
</style>
