<template>
  <div class="system table_form-container">
    <!-- 角色列表头 -->
    <div class="header">
      <h4>角色列表</h4>
      <el-button type="primary" @click="handleAddRole" v-auth="'roles_create'">新增角色</el-button>
    </div>
    <!-- 角色列表表格 -->
    <RoleTable :table-data="roleTree" :columns="roleTableColumns" row-key="id" :loading="loading">
      <template #status="{ row }">
        <el-switch :model-value="row.status === 1" :active-value="true" :inactive-value="false" active-text="启用"
          inactive-text="禁用" />
      </template>
      <template #createTime="{ row }">
        {{ row.created_at }}
      </template>
      <template #action="{ row }">
        <el-button link type="primary" size="small" @click="handleEditRole(row)" v-auth="'roles_edit'">
          编辑
        </el-button>
        <el-button link type="primary" size="small" @click="handlePermission(row)" v-auth="'roles_setPermission'">
          设置权限
        </el-button>
        <el-button link type="danger" size="small" @click="handleDeleteRole(row)" v-auth="'roles_del'">
          删除
        </el-button>
      </template>
    </RoleTable>
  </div>
  <!-- 角色新增/编辑抽屉 -->
  <el-drawer v-model="dialogVisible" :title="dialogTitle" :size="'800px'" @close="handleClose">
    <RoleForm :form-data="roleForm" :form-rules="roleFormRules" :form-items="roleFormItemOptions" ref="roleFormRef"
      :options-map="roleFormOptionsMap" :dialog-type="dialogType">
      <template #permissions="{ formData }">
        <el-tree v-loading="treeLoading" ref="permissionTreeRef" :data="permissionTreeData" :props="treeProps"
          show-checkbox node-key="id" :default-expand-all="true" :check-strictly="false" class="permission-tree" />
      </template>
    </RoleForm>

    <template #footer>
      <div style="flex: auto">
        <el-button @click="handleCancel">取消</el-button>
        <el-button type="primary" :loading="buttonLoading" @click="handleSubmit">确定</el-button>
      </div>
    </template>
  </el-drawer>
</template>

<script lang="ts" setup>

defineOptions({
  name: 'Role'
})
import type { FormInstance, TreeInstance } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import { usePageLoading, useButtonLoading } from '@/composables/useLoading'

const { loading, startLoading, stopLoading } = usePageLoading()
const { loading: treeLoading, startLoading: treeStartLoading, stopLoading: treeStopLoading } = usePageLoading()
const { buttonLoading, startButtonLoading, stopButtonLoading } = useButtonLoading()

// 组件配置
import RoleTable from '@/components/common/Table.vue'
import RoleDialog from '@/components/common/Dialog.vue'
import RoleForm from '@/components/common/Form.vue'
import { roleTableColumns, roleFormItem, permissionsFormItem } from './options'
import { rules } from './rules'

import {
  getRoleApi,
  createRoleApi,
  editRoleApi,
  deleteRoleApi,
  getRolePermissionApi,
  setRolePermissionApi,
} from '@/api/modules/system/role'

// Tree组件的ref
const permissionTreeRef = ref<TreeInstance>()

// 树形数据
const permissionTreeData = ref<any[]>([])

// Tree组件的props配置
const treeProps = {
  label: 'title',
  children: 'children',
}

// 定义header配置
const roleTitle = ref('角色管理')
const roleHeaderButtons = [
  { label: '新增角色', type: 'primary' as const, icon: Plus, key: 'addRole' },
]

// 定义表格配置
const roleTree = ref<any[]>([])

// 定义弹窗配置
const dialogVisible = ref(false)
const dialogTitle = ref('')
const dialogType = ref('add')
const fullScreen = ref(false)

// 定义角色表单数据
const roleForm = ref({
  name: '', // 角色名称
  title: '', // 角色标题
  permissions: [] as number[], // 角色权限
})
const roleFormRef = ref<FormInstance>()
// 表单验证规则
const roleFormRules = rules()
// 角色表单选项
const roleFormItemOptions = ref(roleFormItem)
// 角色表单选项映射
const roleFormOptionsMap = ref({
  permissions: [] as any[],
})

// 保存权限id
const permissionIds = ref('')
// 原始权限列表
const allPermissions = ref<any[]>([])

/**
@description: 新增角色
**/
const handleAddRole = () => {
  console.log('新增角色', dialogType.value)
  dialogVisible.value = true
  dialogTitle.value = '新增角色'
  handleDialogType(dialogType.value)
}

/**
@description: 角色数据处理
**/
// 处理角色状态，只保留 status=1 的角色
const filterRoles = (roleList: any[]) => {
  const enabledRoles = roleList.filter((role) => role.status === 1)
  return enabledRoles
}

// 获取角色列表
const fetchRoleList = async () => {
  startLoading()
  try {
    const data = await getRoleApi()
    roleTree.value = data
  } catch (err) {
    console.error('获取角色列表失败', err)
  } finally {
    stopLoading()
  }
}

// 页面加载时获取菜单列表
onMounted(async () => {
  await fetchRoleList()
})

/**
@description: 处理菜单编辑/删除/状态切换
**/
// 角色编辑
const handleEditRole = (row: any) => {
  dialogVisible.value = true
  dialogTitle.value = '编辑角色'
  dialogType.value = 'edit'
  handleDialogType(dialogType.value)
  roleForm.value = {
    ...row,
    id: row.id, // 角色id
  }
  console.log('编辑角色', dialogType.value)
}
// 角色删除
const handleDeleteRole = async (row: any) => {
  try {
    await deleteRoleApi({ id: row.id })
    await fetchRoleList()
  } catch (err) {
    console.error('删除角色失败')
  }
}

//区分新增和编辑角色表单选项
const handleDialogType = (type: string) => {
  if (type === 'permissions') {
    roleFormItemOptions.value = permissionsFormItem as any
    fullScreen.value = true
    console.log('权限弹窗', fullScreen.value)
  } else {
    roleFormItemOptions.value = roleFormItem as any
    fullScreen.value = false
  }
}

// 将权限数据转换为树形结构
const transformPermissionsToTree = (permissions: any[]) => {
  const moduleMap = new Map<string, any>()
  const childrenMap = new Map<string, any[]>()

  // 首先找出所有模块（作为父节点）
  permissions.forEach((perm) => {
    if (perm.module && !moduleMap.has(perm.module)) {
      // 找到该模块对应的权限项作为父节点
      const moduleItem = permissions.find((p) => p.title === perm.module)
      if (moduleItem) {
        moduleMap.set(perm.module, {
          id: moduleItem.id,
          title: moduleItem.title,
          children: [],
        })
      }
    }
  })

  // 将权限项归类到对应的模块下
  permissions.forEach((perm) => {
    if (perm.module && moduleMap.has(perm.module)) {
      const moduleItem = moduleMap.get(perm.module)!
      // 排除模块本身，只添加子权限
      if (perm.title !== perm.module) {
        moduleItem.children.push({
          id: perm.id,
          title: `${perm.title} (${perm.name})`,
        })
      }
    }
  })

  // 转换为数组并按ID排序
  return Array.from(moduleMap.values()).sort((a, b) => a.id - b.id)
}

/**
 * @description: 过滤掉父节点ID，只保留子节点ID用于显示选中状态
 */
const filterParentNodes = (permissionIds: number[], treeData: any[]): number[] => {
  // 获取所有父节点ID
  const parentNodeIds = treeData.map(node => node.id)
  // 过滤掉父节点ID，只保留子节点ID
  return permissionIds.filter(id => !parentNodeIds.includes(id))
}

/**
 * @description: 根据选中的子节点计算父节点ID（半选中的父节点）
 */
const getParentNodeIds = (checkedKeys: number[], treeData: any[]): number[] => {
  const parentIds: number[] = []

  treeData.forEach(parent => {
    // 获取该父节点下所有子节点的ID
    const childIds = parent.children?.map((child: any) => child.id) || []
    // 检查是否有子节点被选中
    const hasCheckedChild = childIds.some((id: number) => checkedKeys.includes(id))
    // 检查是否所有子节点都被选中
    const allChildrenChecked = childIds.length > 0 && childIds.every((id: number) => checkedKeys.includes(id))

    // 如果有子节点被选中，但不是全部选中，则父节点为半选中状态
    if (hasCheckedChild && !allChildrenChecked) {
      parentIds.push(parent.id)
    }
  })

  return parentIds
}

// 角色权限获取和设置
const handlePermission = async (row: any) => {
  dialogVisible.value = true
  dialogTitle.value = '设置角色权限'
  permissionTreeData.value = []
  dialogType.value = 'permissions'
  treeStartLoading()
  handleDialogType(dialogType.value)
  permissionIds.value = row.id
  try {
    const data = await getRolePermissionApi({ id: row.id })
    allPermissions.value = data.all_permission_info
    permissionTreeData.value = transformPermissionsToTree(data.all_permission_info)

    // 过滤掉父节点ID，只保留子节点ID
    const childPermissionIds = filterParentNodes(data.permission_ids || [], permissionTreeData.value)
    roleForm.value.permissions = childPermissionIds

    console.log('树形权限数据', permissionTreeData.value)
    console.log('过滤后的权限ID（仅子节点）:', childPermissionIds)

    // 等待DOM更新后，手动设置选中状态
    await nextTick()
    // 使用 setCheckedKeys 设置选中状态，只设置子节点
    permissionTreeRef.value?.setCheckedKeys(childPermissionIds, false)
  } catch (err) {
    console.error('获取角色权限失败', err)
  } finally { 
    treeStopLoading()
  }
}

/**
@description: 处理弹窗提交/取消/关闭事件
**/
const handleSubmit = async () => {
  startButtonLoading()
  console.log('提交菜单表单', roleForm.value.permissions, allPermissions.value)
  try {
    await roleFormRef.value?.validate()
    if (dialogType.value === 'add') {
      const params = {
        name: roleForm.value.name,
        title: roleForm.value.title,
      }
      await createRoleApi(params)
      await fetchRoleList()
    } else if (dialogType.value === 'edit') {
      await editRoleApi(roleForm.value)
      await fetchRoleList()
    } else {
      // 获取Tree组件选中的所有节点（包括完全选中和半选中的节点）
      const checkedKeys = permissionTreeRef.value?.getCheckedKeys() || []
      const halfCheckedKeys = permissionTreeRef.value?.getHalfCheckedKeys() || []

      // 合并完全选中和半选中的节点ID
      const allSelectedKeys = [...checkedKeys, ...halfCheckedKeys]

      console.log('设置角色权限 - 完全选中:', checkedKeys)
      console.log('设置角色权限 - 半选中:', halfCheckedKeys)
      console.log('设置角色权限 - 合并后:', allSelectedKeys)

      await setRolePermissionApi({
        id: permissionIds.value,
        permission_ids: allSelectedKeys.join(','),
      })
      await fetchRoleList()
    }
    dialogVisible.value = false
  } catch (err) {
    console.log('表单验证失败')
    return
  } finally {
    stopButtonLoading()
  }
}

// 角色弹窗取消
const handleCancel = () => {
  dialogVisible.value = false
  dialogType.value = 'add'
  roleForm.value = {
    name: '',
    title: '',
    permissions: [] as number[],
  }
}

// 角色弹窗关闭
const handleClose = () => {
  dialogVisible.value = false
  dialogType.value = 'add'
  roleForm.value = {
    name: '',
    title: '',
    permissions: [] as number[],
  }
}
</script>

<style scoped lang="scss">
:deep(.el-form-item__content) {
  margin-left: 0 !important;
}

.system {
  :deep(.el-drawer__header) {
    margin-bottom: 0 !important;
  }
}

.permission-tree {
  width: 100%;
  // border: 1px solid #e5e7eb;
  border-radius: 6px;
  // padding: 15px;
  // max-height: 500px;
  // overflow-y: auto;
}
</style>
