<template>
  <div class="role-management p-1 bg-gray-50 h-screen flex flex-col">
    <!-- 搜索表单和角色表格 -->
    <div class="bg-white rounded-lg shadow-sm border border-gray-100 flex-1 flex flex-col overflow-hidden">
      <!-- 搜索表单 -->
      <div class="px-4 py-2 border-b border-gray-100">
        <n-form
          ref="searchFormRef"
          :model="searchForm"
          label-placement="left"
          label-width="auto"
          class="search-form"
        >
          <n-grid :cols="6" :x-gap="8" :y-gap="4">
            <n-grid-item>
              <n-form-item label="角色名称" path="roleName">
                <n-input
                  v-model:value="searchForm.roleName"
                  placeholder="请输入角色名称"
                  clearable
                  @keydown.enter="handleSearch"
                />
              </n-form-item>
            </n-grid-item>

            <n-grid-item>
              <n-form-item label="角色编码" path="roleCode">
                <n-input
                  v-model:value="searchForm.roleCode"
                  placeholder="请输入角色编码"
                  clearable
                  @keydown.enter="handleSearch"
                />
              </n-form-item>
            </n-grid-item>

            <n-grid-item>
              <n-form-item label="创建时间" path="timeRange">
                <n-date-picker
                  v-model:value="searchForm.timeRange"
                  type="datetimerange"
                  clearable
                  placeholder="选择时间范围"
                  :shortcuts="{
                    今天: () => [new Date().setHours(0, 0, 0, 0), new Date().setHours(23, 59, 59, 999)],
                    昨天: () => {
                      const yesterday = new Date();
                      yesterday.setDate(yesterday.getDate() - 1);
                      return [yesterday.setHours(0, 0, 0, 0), yesterday.setHours(23, 59, 59, 999)];
                    },
                    最近7天: () => [Date.now() - 7 * 24 * 60 * 60 * 1000, Date.now()],
                    最近30天: () => [Date.now() - 30 * 24 * 60 * 60 * 1000, Date.now()],
                  }"
                />
              </n-form-item>
            </n-grid-item>

            <n-grid-item>
              <n-form-item label="角色状态" path="roleStatus">
                <n-select
                  v-model:value="searchForm.roleStatus"
                  placeholder="请选择角色状态"
                  clearable
                  :options="[
                    { label: '启用', value: '0' },
                    { label: '停用', value: '1' },
                  ]"
                />
              </n-form-item>
            </n-grid-item>

            <n-grid-item>
              <n-form-item label="" path="">
                <NSpace>
                  <NButton type="primary" @click="handleSearch">
                    <template #icon>
                      <NIcon><icon-park-outline:search /></NIcon>
                    </template>
                    搜索
                  </NButton>
                  <NButton @click="handleReset">
                    <template #icon>
                      <NIcon><icon-park-outline:refresh /></NIcon>
                    </template>
                    重置
                  </NButton>
                </NSpace>
              </n-form-item>
            </n-grid-item>
          </n-grid>
        </n-form>
      </div>

      <!-- 表格头部操作栏 -->
      <div class="flex items-center justify-between px-4 py-2 border-b border-gray-100">
        <div class="flex items-center gap-4">
          <NButton v-button="PERMISSIONS.ROLE.ADD" type="primary" class="px-6 flex items-center" @click="handleAdd">
            <template #icon>
              <NIcon class="mr-1" style="transform: translateY(-1px)">
                <icon-park-outline:plus />
              </NIcon>
            </template>
            新增
          </NButton>

          <NButton
            v-button="PERMISSIONS.ROLE.DELETE"
            type="error"
            :disabled="selectedRows.length === 0"
            class="px-6 flex items-center"
            @click="handleBatchDelete"
          >
            <template #icon>
              <NIcon class="mr-1" style="transform: translateY(-1px)">
                <icon-park-outline:delete />
              </NIcon>
            </template>
            删除
          </NButton>
        </div>

        <div class="flex items-center gap-4 text-sm text-gray-500">
          <span>共 {{ pagination.itemCount }} 条</span>
          <NButton text @click="getRoleList">
            <template #icon>
              <NIcon><icon-park-outline:refresh /></NIcon>
            </template>
          </NButton>
        </div>
      </div>

      <!-- 表格内容 -->
      <div class="table-wrapper flex-1 overflow-auto pt-4">
        <n-data-table
          :columns="columns"
          :data="tableData"
          :loading="loading"
          :row-key="(row: RoleVo) => row.roleId"
          :bordered="false"
          :single-line="false"
          size="large"
          class="custom-table"
          @update:checked-row-keys="handleRowSelectionChange"
        />
      </div>

      <!-- 分页器 -->
      <div class="flex items-center px-4 py-2 border-t border-gray-100">
        <div class="text-sm text-gray-500 mr-4">
          共 {{ pagination.itemCount }} 条
        </div>
        <n-pagination
          v-model:page="pagination.page"
          v-model:page-size="pagination.pageSize"
          :item-count="pagination.itemCount"
          :show-size-picker="true"
          :page-sizes="[10, 20, 50, 100]"
          show-quick-jumper
          @update:page="handlePageChange"
          @update:page-size="handlePageSizeChange"
        />
      </div>
    </div>

    <!-- 角色表单弹框 -->
    <NovaDialog
      ref="roleDialogRef"
      :title="modalTitle"
      :width="700"
      height="auto"
      confirm-text="确定"
      cancel-text="取消"
      @nova-confirm="handleSubmit"
      @nova-cancel="handleCancel"
    >
      <template #content>
        <div class="px-3 py-2">
          <n-form
            ref="formRef"
            :model="formData"
            :rules="rules"
            label-placement="left"
            label-width="90px"
            require-mark-placement="right-hanging"
          >
            <!-- 第一行：角色名称 和 角色编码 -->
            <n-grid :cols="2" :x-gap="12">
              <n-grid-item>
                <n-form-item label="角色名称" path="roleName">
                  <n-input
                    v-model:value="formData.roleName"
                    placeholder="请输入角色名称"
                  />
                </n-form-item>
              </n-grid-item>
              <n-grid-item>
                <n-form-item label="角色编码" path="roleCode">
                  <n-input
                    v-model:value="formData.roleCode"
                    placeholder="请输入角色编码"
                    :disabled="isEdit"
                  />
                </n-form-item>
              </n-grid-item>
            </n-grid>

            <!-- 第二行：角色状态 和 显示排序 -->
            <n-grid :cols="2" :x-gap="12">
              <n-grid-item>
                <n-form-item label="角色状态" path="roleStatus">
                  <n-select
                    v-model:value="formData.roleStatus"
                    placeholder="请选择角色状态"
                    :options="[
                      { label: '启用', value: '0' },
                      { label: '停用', value: '1' },
                    ]"
                  />
                </n-form-item>
              </n-grid-item>
              <n-grid-item>
                <n-form-item label="显示排序" path="sorted">
                  <n-input-number
                    v-model:value="formData.sorted"
                    placeholder="请输入排序号"
                    :min="1"
                    :max="999"
                    style="width: 100%"
                  />
                </n-form-item>
              </n-grid-item>
            </n-grid>

            <!-- 第三行：角色描述（占满整行） -->
            <n-form-item label="角色描述" path="remark">
              <n-input
                v-model:value="formData.remark"
                type="textarea"
                placeholder="请输入角色描述"
                :rows="3"
              />
            </n-form-item>
          </n-form>
        </div>
      </template>
    </NovaDialog>

    <!-- 菜单权限分配弹框 -->
    <NovaDialog
      ref="menuDialogRef"
      title="分配菜单权限"
      :width="500"
      height="auto"
      confirm-text="确定"
      cancel-text="取消"
      @nova-confirm="handleConfirmAssignMenu"
      @nova-cancel="handleCancelAssignMenu"
    >
      <template #content>
        <div class="p-3">
          <div v-if="menuLoading" class="flex items-center justify-center py-8">
            <div class="text-center">
              <n-spin size="medium" />
              <p class="mt-2 text-sm text-gray-500">
                正在加载菜单数据...
              </p>
            </div>
          </div>

          <div v-else-if="menuData.length > 0">
            <!-- 功能按钮区域 -->
            <div class="flex items-center gap-2 mb-3 pb-3 border-b border-gray-200">
              <NButton
                size="small"
                :type="allExpanded ? 'default' : 'primary'"
                @click="toggleExpandAll"
              >
                {{ allExpanded ? '折叠' : '展开' }}
              </NButton>

              <NButton
                size="small"
                :type="allSelected ? 'default' : 'primary'"
                @click="toggleSelectAll"
              >
                {{ allSelected ? '全不选' : '全选' }}
              </NButton>

              <NButton
                size="small"
                :type="cascadeEnabled ? 'primary' : 'default'"
                @click="toggleCascade"
              >
                父子联动
              </NButton>

              <NButton
                size="small"
                :type="showPermissionCode ? 'primary' : 'default'"
                @click="togglePermissionCode"
              >
                权限标识
              </NButton>
            </div>

            <NTree
              v-model:checked-keys="checkedKeys"
              v-model:expanded-keys="expandedKeys"
              :data="menuData"
              checkable
              :cascade="cascadeEnabled"
              check-strategy="all"
              expand-on-click
              :render-suffix="showPermissionCode ? renderPermissionCode : undefined"
              class="clean-menu-tree"
            />
          </div>

          <div v-else class="flex items-center justify-center py-8">
            <div class="text-center">
              <div class="w-10 h-10 bg-gray-100 rounded-full flex items-center justify-center mx-auto mb-2">
                <NIcon size="16" class="text-gray-400">
                  <icon-park-outline:folder-close />
                </NIcon>
              </div>
              <p class="text-sm text-gray-500">
                暂无可分配的菜单
              </p>
            </div>
          </div>
        </div>
      </template>
    </NovaDialog>
  </div>
</template>

<script setup lang="ts">
import { h, nextTick, onMounted, ref, watch } from 'vue'
import type { DataTableColumns, FormInst } from 'naive-ui'
import { NButton, NIcon, NPopconfirm, NSpace, NSwitch, NTag, NTree } from 'naive-ui'
import NovaDialog from '@/components/common/NovaDialog.vue'
import {
  addRole,
  batchDeleteRoles,
  deleteRole,
  getRolePage,
  getRoleSorted,
  updateRole,
  updateRoleStatus,
} from '@/service/api/system/role'
import type { RoleForm, RoleSearchForm, RoleVo } from '@/service/api/system/role'

import {
  fetchMenuIdsByRoleId,
  fetchMenuPermissionData,
  saveRoleMenuPermission,
} from '@/service/api/system/menu'
import type { MenuPermissionData, MenuVo } from '@/service/api/system/menu'
import { coiMsgBox, coiMsgError, coiMsgSuccess, coiMsgWarning } from '@/utils/coi'
import { PERMISSIONS } from '@/constants/permissions'
import { usePermission } from '@/hooks/usePermission'

// 权限相关
const { hasButton } = usePermission()

// 响应式数据
const loading = ref(false)
const tableData = ref<RoleVo[]>([])
const modalTitle = ref('新增角色')
const formRef = ref<FormInst | null>(null)
const searchFormRef = ref<FormInst | null>(null)
const isEdit = ref(false)
const currentRole = ref<RoleVo | null>(null)
const selectedRows = ref<RoleVo[]>([])

// 弹框引用
const roleDialogRef = ref()
const menuDialogRef = ref()

// 菜单权限分配相关
const menuModalTitle = ref('分配菜单权限')
const currentAssignRole = ref<RoleVo | null>(null)
const menuData = ref<any[]>([])
const expandedKeys = ref<string[]>([])
const checkedKeys = ref<string[]>([])
const menuLoading = ref(false)

// 功能按钮状态
const allExpanded = ref(false)
const allSelected = ref(false)
const cascadeEnabled = ref(true)
const showPermissionCode = ref(false)

// 分页数据
const pagination = ref({
  page: 1,
  pageSize: 10,
  itemCount: 0,
  showSizePicker: true,
  pageSizes: [10, 20, 50, 100],
})

// 搜索表单数据
const searchForm = ref<RoleSearchForm>({})

// 表单数据
const formData = ref<RoleForm>({
  roleName: '',
  roleCode: '',
  roleStatus: '0',
  remark: '',
  sorted: 1,
})

// 表单验证规则
const rules = {
  roleName: [
    { required: true, message: '请输入角色名称', trigger: 'blur' },
    { min: 2, max: 20, message: '角色名称长度为 2-20 位', trigger: 'blur' },
  ],
  roleCode: [
    { required: true, message: '请输入角色编码', trigger: 'blur' },
    { min: 2, max: 20, message: '角色编码长度为 2-20 位', trigger: 'blur' },
    { pattern: /^\w+$/, message: '角色编码只能包含字母、数字和下划线', trigger: 'blur' },
  ],
  roleStatus: [
    { required: true, message: '请选择角色状态', trigger: 'change' },
  ],
}

// 表格列定义
const columns: DataTableColumns<RoleVo> = [
  {
    type: 'selection',
    width: 50,
    disabled: (row: RoleVo) => row.roleId === 1, // 超级管理员不可选择
  },
  {
    title: '序号',
    key: 'index',
    width: 70,
    align: 'center',
    render: (_, index) => {
      return (pagination.value.page - 1) * pagination.value.pageSize + index + 1
    },
  },
  {
    title: '角色名称',
    key: 'roleName',
    width: 150,
    align: 'center',
    render: (row) => {
      return h('span', { class: 'text-gray-600' }, row.roleName)
    },
  },
  {
    title: '角色编码',
    key: 'roleCode',
    width: 150,
    align: 'center',
    render: (row) => {
      return h('code', { class: 'bg-gray-100 px-2 py-1 rounded text-sm text-blue-600' }, row.roleCode)
    },
  },
  {
    title: '角色状态',
    key: 'roleStatus',
    width: 100,
    align: 'center',
    render: (row) => {
      return h('div', { class: 'flex items-center justify-center' }, [
        h(NPopconfirm, {
          onPositiveClick: () => handleToggleStatus(row),
          negativeText: '取消',
          positiveText: '确定',
        }, {
          default: () => `确定要${row.roleStatus === '0' ? '停用' : '启用'}角色「${row.roleName}」吗？`,
          trigger: () => h(NSwitch, {
            value: row.roleStatus === '0',
            size: 'small',
            checkedChildren: '启用',
            uncheckedChildren: '停用',
            loading: false,
          }),
        }),
      ])
    },
  },
  {
    title: '角色描述',
    key: 'remark',
    width: 200,
    align: 'center',
    ellipsis: { tooltip: true },
    render: (row) => {
      return h('span', { class: 'text-gray-600' }, row.remark || '-')
    },
  },
  {
    title: '排序',
    key: 'sorted',
    width: 80,
    align: 'center',
    render: (row) => {
      return h(NTag, { type: 'info', size: 'small' }, { default: () => row.sorted || '-' })
    },
  },
  {
    title: '创建时间',
    key: 'createTime',
    width: 160,
    align: 'center',
    render: (row) => {
      return h('span', { class: 'text-gray-500 text-sm' }, row.createTime || '-')
    },
  },
  {
    title: '操作',
    key: 'actions',
    width: 280,
    align: 'center',
    fixed: 'right',
    render: (row) => {
      const buttons = []

      // 编辑按钮
      if (hasButton(PERMISSIONS.ROLE.UPDATE)) {
        buttons.push(h(NButton, {
          type: 'primary',
          size: 'small',
          onClick: () => handleEdit(row),
        }, {
          icon: () => h(NIcon, { size: 14, style: 'transform: translateY(-1px)' }, { default: () => h('icon-park-outline:edit') }),
          default: () => '编辑',
        }))
      }

      // 删除按钮
      if (hasButton(PERMISSIONS.ROLE.DELETE)) {
        buttons.push(h(NPopconfirm, {
          onPositiveClick: () => handleDelete(row.roleId),
          negativeText: '取消',
          positiveText: '确定',
        }, {
          default: () => row.roleId === 1 ? '超级管理员角色不可删除' : '确定删除此角色吗？',
          trigger: () => h(NButton, {
            type: 'error',
            size: 'small',
            disabled: row.roleId === 1,
          }, {
            icon: () => h(NIcon, { size: 14, style: 'transform: translateY(-1px)' }, { default: () => h('icon-park-outline:delete') }),
            default: () => '删除',
          }),
        }))
      }

      // 分配权限按钮 - 超级管理员不显示
      if (hasButton(PERMISSIONS.ROLE.MENU) && row.roleId !== 1) {
        buttons.push(h(NButton, {
          type: 'warning',
          size: 'small',
          onClick: () => handleAssignMenu(row),
        }, {
          icon: () => h(NIcon, { size: 14, style: 'transform: translateY(-1px)' }, { default: () => h('icon-park-outline:setting') }),
          default: () => '分配权限',
        }))
      }

      return h('div', { class: 'flex items-center justify-center gap-2' }, buttons)
    },
  },
]

// 构建树形菜单数据
function buildMenuTree(menuList: MenuVo[]): any[] {
  const map = new Map()
  const result: any[] = []

  // 先将所有菜单存入map，确保key的唯一性和类型一致性
  menuList.forEach((menu) => {
    const permissionCode = menu.auth || menu.perms || menu.permission || ''
    map.set(menu.menuId, {
      key: String(menu.menuId), // 确保key为字符串类型
      label: menu.menuName,
      menuId: menu.menuId,
      parentId: menu.parentId,
      menuType: menu.menuType,
      auth: menu.auth || '', // 权限标识
      perms: permissionCode, // 权限标识
      permissionCode, // 权限标识的别名
    })
  })

  // 构建树形结构
  menuList.forEach((menu) => {
    const node = map.get(menu.menuId)
    if (menu.parentId === 0) {
      result.push(node)
    }
    else {
      const parent = map.get(menu.parentId)
      if (parent) {
        if (!parent.children) {
          parent.children = []
        }
        parent.children.push(node)
      }
    }
  })

  // 清理空的children数组，让叶子节点真正成为叶子节点
  function cleanEmptyChildren(nodes: any[]) {
    nodes.forEach((node) => {
      if (node.children && node.children.length === 0) {
        delete node.children
      }
      else if (node.children && node.children.length > 0) {
        cleanEmptyChildren(node.children)
      }
    })
  }

  cleanEmptyChildren(result)
  return result
}

// 获取角色列表
async function getRoleList() {
  loading.value = true
  try {
    // 构建请求参数，处理时间范围
    const { timeRange, ...otherParams } = searchForm.value

    // 过滤掉空值和null值，只保留有效的搜索条件
    const filteredParams = Object.entries(otherParams).reduce((acc, [key, value]) => {
      if (value !== null && value !== undefined && value !== '') {
        acc[key] = value
      }
      return acc
    }, {} as Record<string, any>)

    const params: any = {
      pageNo: pagination.value.page,
      pageSize: pagination.value.pageSize,
      ...filteredParams,
    }

    // 处理时间范围，转换为beginTime和endTime（需要后端支持）
    if (timeRange && timeRange.length === 2) {
      // 使用本地时间格式，避免时区问题
      const startDate = new Date(timeRange[0])
      const endDate = new Date(timeRange[1])

      // 格式化为 yyyy-MM-dd HH:mm:ss 格式
      params.beginTime = `${startDate.getFullYear()}-${String(startDate.getMonth() + 1).padStart(2, '0')}-${String(startDate.getDate()).padStart(2, '0')} ${String(startDate.getHours()).padStart(2, '0')}:${String(startDate.getMinutes()).padStart(2, '0')}:${String(startDate.getSeconds()).padStart(2, '0')}`
      params.endTime = `${endDate.getFullYear()}-${String(endDate.getMonth() + 1).padStart(2, '0')}-${String(endDate.getDate()).padStart(2, '0')} ${String(endDate.getHours()).padStart(2, '0')}:${String(endDate.getMinutes()).padStart(2, '0')}:${String(endDate.getSeconds()).padStart(2, '0')}`
    }

    const { isSuccess, data } = await getRolePage(params)

    if (isSuccess && data) {
      tableData.value = data.records || []
      pagination.value.itemCount = data.total || 0
    }
    else {
      coiMsgError('获取角色列表失败，请检查网络连接或联系管理员')
      tableData.value = []
      pagination.value.itemCount = 0
    }
  }
  catch {
    coiMsgError('获取角色列表失败，请检查网络连接')
    tableData.value = []
    pagination.value.itemCount = 0
  }
  finally {
    loading.value = false
  }
}

// 分页变化处理
function handlePageChange(page: number) {
  pagination.value.page = page
  getRoleList()
}

function handlePageSizeChange(pageSize: number) {
  pagination.value.pageSize = pageSize
  pagination.value.page = 1
  getRoleList()
}

// 搜索
function handleSearch() {
  pagination.value.page = 1
  getRoleList()
}

// 重置搜索
async function handleReset() {
  // 重置搜索表单的所有字段
  searchForm.value = {
    roleName: '',
    roleCode: '',
    roleStatus: null,
    timeRange: null,
  }

  // 使用 nextTick 确保 DOM 更新后再重置表单状态
  await nextTick()

  // 重置表单验证状态
  if (searchFormRef.value) {
    searchFormRef.value.restoreValidation()
  }

  // 重置分页到第一页
  pagination.value.page = 1
  // 重新获取数据
  getRoleList()
}

// 行选择变化
function handleRowSelectionChange(rowKeys: (string | number)[]) {
  const numericKeys = rowKeys.map(key => typeof key === 'string' ? Number.parseInt(key) : key)
  selectedRows.value = tableData.value.filter(row => numericKeys.includes(row.roleId))
}

// 新增角色
async function handleAdd() {
  modalTitle.value = '新增角色'
  isEdit.value = false
  currentRole.value = null

  try {
    // 获取最新排序号
    const { isSuccess, data } = await getRoleSorted()
    const sorted = isSuccess && data ? data : 1

    formData.value = {
      roleName: '',
      roleCode: '',
      roleStatus: '0',
      remark: '',
      sorted,
    }
  }
  catch {
    formData.value = {
      roleName: '',
      roleCode: '',
      roleStatus: '0',
      remark: '',
      sorted: 1,
    }
  }

  roleDialogRef.value?.novaOpen()
}

// 编辑角色
function handleEdit(role: RoleVo) {
  modalTitle.value = '编辑角色'
  isEdit.value = true
  currentRole.value = role
  formData.value = {
    roleId: role.roleId,
    roleName: role.roleName,
    roleCode: role.roleCode,
    roleStatus: role.roleStatus,
    remark: role.remark || '',
    sorted: role.sorted || 1,
  }
  roleDialogRef.value?.novaOpen()
}

// 删除角色
async function handleDelete(roleId: number) {
  if (roleId === 1) {
    coiMsgError('超级管理员角色不可删除')
    return
  }

  try {
    const { isSuccess } = await deleteRole(roleId)
    if (isSuccess) {
      coiMsgSuccess('删除成功')
      await getRoleList()
    }
    else {
      coiMsgError('删除失败')
    }
  }
  catch {
    coiMsgError('删除失败')
  }
}

// 批量删除角色
async function handleBatchDelete() {
  if (selectedRows.value.length === 0) {
    coiMsgWarning('请先选择要删除的角色')
    return
  }

  // 检查是否包含超级管理员角色
  const hasSuperAdmin = selectedRows.value.some(role => role.roleId === 1)
  if (hasSuperAdmin) {
    coiMsgError('所选角色中包含超级管理员，无法批量删除')
    return
  }

  try {
    // 确认删除操作
    await coiMsgBox(`确定要删除选中的 ${selectedRows.value.length} 个角色吗？`, '批量删除确认')
  }
  catch {
    // 用户取消删除操作，直接返回，不显示任何提示
    return
  }

  // 用户确认删除，执行删除操作
  try {
    const roleIds = selectedRows.value.map(role => role.roleId)
    const { isSuccess } = await batchDeleteRoles(roleIds)
    if (isSuccess) {
      coiMsgSuccess('批量删除成功')
      selectedRows.value = []
      await getRoleList()
    }
    else {
      coiMsgError('批量删除失败')
    }
  }
  catch {
    coiMsgError('批量删除失败')
  }
}

// 切换角色状态
async function handleToggleStatus(role: RoleVo) {
  try {
    const newStatus = role.roleStatus === '0' ? '1' : '0'
    const statusText = newStatus === '0' ? '启用' : '停用'

    const { isSuccess } = await updateRoleStatus(role.roleId, newStatus)
    if (isSuccess) {
      role.roleStatus = newStatus
      coiMsgSuccess(`角色「${role.roleName}」${statusText}成功`)
      // 刷新角色列表以确保数据同步
      await getRoleList()
    }
    else {
      coiMsgError(`角色${statusText}失败`)
    }
  }
  catch {
    coiMsgError('状态修改失败，请检查网络连接')
  }
}

// 分配菜单权限
async function handleAssignMenu(role: RoleVo) {
  if (!role?.roleId) {
    coiMsgError('角色信息无效')
    return
  }

  try {
    menuLoading.value = true
    currentAssignRole.value = role
    menuModalTitle.value = `分配菜单权限 - ${role.roleName}`

    // 重置状态
    menuData.value = []
    expandedKeys.value = []
    checkedKeys.value = []

    // 获取菜单权限数据
    const menuResponse = await fetchMenuPermissionData()

    if (menuResponse.isSuccess && menuResponse.data) {
      const permissionData = menuResponse.data as MenuPermissionData
      menuData.value = buildMenuTree(permissionData.menuList)

      // 将展开的节点ID转换为字符串格式，保持与key格式一致
      expandedKeys.value = (permissionData.spreadList || []).map(id => String(id))

      // 获取当前角色的菜单权限
      const roleMenuResponse = await fetchMenuIdsByRoleId(role.roleId)
      if (roleMenuResponse.isSuccess && roleMenuResponse.data) {
        // 将权限ID转换为字符串格式，保持与key格式一致
        checkedKeys.value = roleMenuResponse.data.map(id => String(id))
      }

      menuDialogRef.value?.novaOpen()
    }
    else {
      coiMsgError('获取菜单数据失败')
    }
  }
  catch {
    coiMsgError('获取菜单数据失败，请检查网络连接')
  }
  finally {
    menuLoading.value = false
  }
}

// 确保选中子菜单时父菜单也被包含
function ensureParentMenusIncluded(selectedIds: string[], menuTree: any[]): string[] {
  const allMenuMap = new Map<number, any>()
  const result = new Set(selectedIds)

  // 递归收集所有菜单项到map中
  function collectMenus(menus: any[]) {
    menus.forEach((menu) => {
      allMenuMap.set(menu.menuId, menu)
      if (menu.children && menu.children.length > 0) {
        collectMenus(menu.children)
      }
    })
  }

  collectMenus(menuTree)

  // 为每个选中的菜单添加其所有父菜单
  selectedIds.forEach((menuIdStr) => {
    const menuId = Number.parseInt(menuIdStr)
    const menu = allMenuMap.get(menuId)
    if (menu && menu.parentId !== 0) {
      let parentId = menu.parentId
      while (parentId && parentId !== 0) {
        result.add(String(parentId))
        const parentMenu = allMenuMap.get(parentId)
        if (parentMenu && parentMenu.parentId !== 0) {
          parentId = parentMenu.parentId
        }
        else {
          break
        }
      }
    }
  })

  return Array.from(result)
}

// 确认分配菜单权限
async function handleConfirmAssignMenu() {
  if (!currentAssignRole.value) {
    coiMsgError('角色信息缺失')
    return
  }

  try {
    menuLoading.value = true

    // 确保选中子菜单时父菜单也被包含
    const completeMenuIds = ensureParentMenusIncluded(checkedKeys.value, menuData.value)

    // 将字符串格式的key转换为数字格式发送给后端
    const menuIds = completeMenuIds.map(key => Number.parseInt(String(key)))
    const response = await saveRoleMenuPermission(currentAssignRole.value.roleId, menuIds)

    if (response.isSuccess) {
      coiMsgSuccess('菜单权限分配成功')
      menuDialogRef.value?.novaClose()
    }
    else {
      coiMsgError(response.message || '菜单权限分配失败')
    }
  }
  catch {
    coiMsgError('菜单权限分配失败，请检查网络连接')
  }
  finally {
    menuLoading.value = false
  }
}

// 取消分配菜单权限
function handleCancelAssignMenu() {
  menuDialogRef.value?.novaClose()
  currentAssignRole.value = null
  menuData.value = []
  expandedKeys.value = []
  checkedKeys.value = []
  menuModalTitle.value = '分配菜单权限'
  menuLoading.value = false
  // 重置功能按钮状态
  allExpanded.value = false
  allSelected.value = false
  cascadeEnabled.value = true
  showPermissionCode.value = false
}

// 获取所有菜单节点的key
function getAllMenuKeys(menus: any[]): string[] {
  const keys: string[] = []
  function traverse(nodes: any[]) {
    nodes.forEach((node) => {
      keys.push(node.key)
      if (node.children && node.children.length > 0) {
        traverse(node.children)
      }
    })
  }
  traverse(menus)
  return keys
}

// 展开/折叠所有节点
function toggleExpandAll() {
  if (allExpanded.value) {
    // 折叠所有
    expandedKeys.value = []
    allExpanded.value = false
  }
  else {
    // 展开所有
    expandedKeys.value = getAllMenuKeys(menuData.value)
    allExpanded.value = true
  }
}

// 全选/全不选
function toggleSelectAll() {
  if (allSelected.value) {
    // 全不选
    checkedKeys.value = []
    allSelected.value = false
  }
  else {
    // 全选
    checkedKeys.value = getAllMenuKeys(menuData.value)
    allSelected.value = true
  }
}

// 切换父子联动
function toggleCascade() {
  cascadeEnabled.value = !cascadeEnabled.value
}

// 切换权限标识显示
function togglePermissionCode() {
  showPermissionCode.value = !showPermissionCode.value
}

// 渲染权限标识
function renderPermissionCode({ option }: { option: any }) {
  const code = option.auth || option.perms || option.permissionCode || ''

  // 如果没有权限标识，返回null
  if (!code || code.trim() === '') {
    return null
  }

  return h('span', {
    class: 'ml-2 px-2 py-1 bg-blue-50 text-blue-600 text-xs rounded font-mono border border-blue-200',
    style: 'font-size: 11px; line-height: 1.2; transform: translateY(-5px); display: inline-flex; align-items: center;',
  }, code)
}

// 提交表单
async function handleSubmit() {
  if (!formRef.value)
    return

  try {
    // 先进行表单验证
    await formRef.value.validate()
  }
  catch {
    // 表单验证失败，提示用户检查填写内容
    coiMsgWarning('验证失败，请检查填写内容')
    return
  }

  // 表单验证通过，执行API调用
  try {
    const submitData = { ...formData.value }

    const { isSuccess } = isEdit.value ? await updateRole(submitData) : await addRole(submitData)

    if (isSuccess) {
      coiMsgSuccess(isEdit.value ? '角色信息更新成功' : '角色创建成功')
      roleDialogRef.value?.novaClose()
      await getRoleList()
    }
    else {
      coiMsgError(isEdit.value ? '更新失败，请稍后重试' : '创建失败，请稍后重试')
    }
  }
  catch {
    coiMsgError(isEdit.value ? '更新失败，请检查网络连接' : '创建失败，请检查网络连接')
  }
}

// 取消操作
function handleCancel() {
  roleDialogRef.value?.novaClose()
}
// 监听选中状态变化，自动更新全选按钮状态
watch(checkedKeys, (newKeys) => {
  const allKeys = getAllMenuKeys(menuData.value)
  allSelected.value = allKeys.length > 0 && newKeys.length === allKeys.length
}, { deep: true })

// 监听展开状态变化，自动更新展开按钮状态
watch(expandedKeys, (newKeys) => {
  const allKeys = getAllMenuKeys(menuData.value)
  allExpanded.value = allKeys.length > 0 && newKeys.length === allKeys.length
}, { deep: true })

// 组件挂载时获取数据
onMounted(() => {
  getRoleList()
})
</script>

<style scoped>
.role-management {
  height: 100vh;
  overflow: hidden;
}

.custom-table :deep(.n-data-table-td) {
  padding: 8px 12px;
}

.custom-table :deep(.n-data-table-th) {
  padding: 10px 12px;
  background-color: #fafafa;
  font-weight: 600;
  color: #262626;
}

.custom-table :deep(.n-data-table-tr:hover .n-data-table-td) {
  background-color: #f8faff;
}

.search-form :deep(.n-form-item-label) {
  font-weight: 500;
  color: #262626;
}

.role-modal :deep(.n-card-header) {
  padding: 24px 24px 0;
  font-size: 18px;
  font-weight: 600;
}

.role-modal :deep(.n-card__content) {
  padding: 24px;
}

/* 优化后的菜单权限分配模态框样式 */
.menu-assign-modal {
  backdrop-filter: blur(8px);
}

.menu-assign-modal :deep(.n-card) {
  border-radius: 16px;
  box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.menu-assign-modal :deep(.n-card-header) {
  padding: 24px 28px 0;
  border-bottom: 1px solid #f1f5f9;
  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
  border-radius: 16px 16px 0 0;
}

.menu-assign-modal :deep(.n-card__content) {
  padding: 24px 28px;
  background: #ffffff;
}

.menu-assign-modal :deep(.n-card__footer) {
  padding: 20px 28px 24px;
  border-top: 1px solid #f1f5f9;
  background: #fafbfc;
  border-radius: 0 0 16px 16px;
}

/* 简洁的菜单树样式 */
.clean-menu-tree {
  background: transparent;
}

.clean-menu-tree :deep(.n-tree-node) {
  margin: 2px 0;
  border-radius: 4px;
  transition: background 0.15s;
}

.clean-menu-tree :deep(.n-tree-node:hover) {
  background: rgba(59, 130, 246, 0.05);
}

/* 去掉选中时的背景色 */
.clean-menu-tree :deep(.n-tree-node--selected) {
  background: transparent !important;
}

.clean-menu-tree :deep(.n-tree-node--selected:hover) {
  background: rgba(59, 130, 246, 0.05) !important;
}

.clean-menu-tree :deep(.n-tree-node-content) {
  padding: 6px 8px;
  min-height: 32px;
  align-items: center;
  display: flex;
}

.clean-menu-tree :deep(.n-tree-node-content__text) {
  flex: 1;
  font-size: 14px;
  color: #374151;
  line-height: 1.5;
  font-weight: 400;
  display: flex;
  align-items: center;
  transform: translateY(-5px);
}

.clean-menu-tree :deep(.n-checkbox) {
  margin-right: 8px;
  display: flex;
  align-items: center;
}

/* 移除选中状态的背景色 */
.clean-menu-tree :deep(.n-tree-node--selected),
.clean-menu-tree :deep(.n-tree-node--selected .n-tree-node-content),
.clean-menu-tree :deep(.n-tree-node-content--selected) {
  background-color: transparent !important;
}

/* 移除悬停状态的背景色变化 */
.clean-menu-tree :deep(.n-tree-node-content:hover) {
  background-color: transparent !important;
}

.clean-menu-tree :deep(.n-tree-node-switcher) {
  margin-right: 4px;
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  transform: translateY(5px);
}

.clean-menu-tree :deep(.n-tree-node-switcher .n-base-icon) {
  font-size: 14px;
  color: #9ca3af;
}

/* 隐藏叶子节点的展开图标 */
.clean-menu-tree :deep(.n-tree-node--leaf .n-tree-node-switcher) {
  visibility: hidden;
}

/* 模态框样式优化 */
.menu-assign-modal :deep(.n-card) {
  border-radius: 8px;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}

.menu-assign-modal :deep(.n-card-header) {
  padding: 16px 20px;
  border-bottom: 1px solid #e5e7eb;
  background: #fafafa;
}

.menu-assign-modal :deep(.n-card__content) {
  padding: 16px 20px;
}

.menu-assign-modal :deep(.n-card__footer) {
  padding: 12px 20px;
  border-top: 1px solid #e5e7eb;
  background: #fafafa;
}

/* 响应式设计 */
@media (max-width: 900px) {
  .menu-assign-modal :deep(.n-card) {
    margin: 10px;
    width: calc(100% - 20px) !important;
    max-height: calc(100vh - 20px);
  }
}

@media (min-width: 1200px) {
  .menu-assign-modal :deep(.n-card) {
    width: 900px !important;
  }
}
</style>
