<template>
  <el-drawer
    v-model="dialogVisible"
    :with-header="false"
    append-to-body
    class="role-permission-drawer"
    direction="rtl"
    size="640px"
  >
    <div class="role-permission-drawer__shell">
      <div class="role-permission-drawer__header">
        <div class="role-permission-drawer__title">
          <el-button text circle class="role-permission-drawer__close" @click="dialogVisible = false">
            <Icon icon="ep:close" />
          </el-button>
          <span>{{ t('SystemManagement.Role.menuPermission') }}</span>
        </div>
        <el-dropdown trigger="click">
          <el-button>
            更多操作
            <Icon icon="ep:arrow-down" class="ml-4px" />
          </el-button>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item @click="handleCheckedTreeNodeAll">
                {{ t('SystemManagement.Role.selectAll') }}
              </el-dropdown-item>
              <el-dropdown-item @click="handleCheckedTreeExpand">
                {{ t('SystemManagement.Role.expandCollapse') }}
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>

      <div class="role-permission-drawer__body">
    <el-form
      ref="formRef"
      v-loading="formLoading"
      :model="formData"
      label-width="auto"
      class="role-assign-menu-form"
    >
      <div class="role-assign-menu-form__meta-row">
        <el-form-item :label="t('SystemManagement.Role.name')" class="role-assign-menu-form__meta">
          <el-tag>{{ formData.name }}</el-tag>
        </el-form-item>
        <el-form-item :label="t('SystemManagement.Role.code')" class="role-assign-menu-form__meta">
          <el-tag>{{ formData.code }}</el-tag>
        </el-form-item>
      </div>
      <el-form-item label-width="0" class="role-assign-menu-form__permission">
        <div class="role-permission-tree-panel">
          <div class="role-permission-tree-panel__title">所拥有的权限</div>
            <div class="role-assign-menu-form__header">
              <el-tabs v-model="activeClientType" @tab-change="handleClientTypeChange">
                <el-tab-pane :label="t('SystemManagement.Menu.clientTypeWeb')" :name="1" />
                <el-tab-pane :label="t('SystemManagement.Menu.clientTypeApp')" :name="2" />
              </el-tabs>
              <div class="role-assign-menu-form__actions">
            {{ t('SystemManagement.Role.selectAll') }}:
            <el-switch
              v-model="treeNodeAll"
              :active-text="t('SystemManagement.Role.yes')"
              :inactive-text="t('SystemManagement.Role.no')"
              inline-prompt
              @change="handleCheckedTreeNodeAll"
            />
            {{ t('SystemManagement.Role.expandCollapse') }}:
            <el-switch
              v-model="menuExpand"
              :active-text="t('SystemManagement.Role.yes')"
              :inactive-text="t('SystemManagement.Role.no')"
              inline-prompt
              @change="handleCheckedTreeExpand"
            />
              </div>
            </div>
          <el-tree
            ref="treeRef"
            class="role-permission-tree"
            :data="menuOptions"
            :props="defaultProps"
            :empty-text="t('SystemManagement.Role.loadingText')"
            node-key="id"
            show-checkbox
          />
        </div>
      </el-form-item>
    </el-form>
      </div>

      <div class="role-permission-drawer__footer">
        <el-button @click="dialogVisible = false">{{ t('common.cancel') }}</el-button>
        <el-button :disabled="formLoading" @click="submitForm">仅保存</el-button>
        <el-button :disabled="formLoading" type="primary" @click="submitForm">保存并关闭</el-button>
      </div>
    </div>
  </el-drawer>
</template>
<script lang="ts" setup>
import { defaultProps, handleTree } from '@/utils/tree'
import * as RoleApi from '@/api/system/role'
import * as MenuApi from '@/api/system/menu'
import * as PermissionApi from '@/api/system/permission'

defineOptions({ name: 'SystemRoleAssignMenuForm' })

interface RoleAssignMenuFormData {
  id: number | undefined
  name: string
  code: string
  menuIds: number[]
}

const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

const dialogVisible = ref(false) // 弹窗的是否展示
const formLoading = ref(false) // 表单的加载中：1）修改时的数据加载；2）提交的按钮禁用
const formData = reactive<RoleAssignMenuFormData>({
  id: undefined,
  name: '',
  code: '',
  menuIds: []
})
const formRef = ref() // 表单 Ref
const menuOptions = ref<any[]>([]) // 菜单树形结构
const menuExpand = ref(false) // 展开/折叠
const treeRef = ref() // 菜单树组件 Ref
const treeNodeAll = ref(false) // 全选/全不选
const activeClientType = ref(1) // 客户端类型：1=Web，2=APP
const currentTreeClientType = ref(1) // 当前树实际对应的客户端类型
const roleMenuIdsByClientType = reactive<Record<number, number[]>>({
  1: [],
  2: []
})
const loadedClientTypes = reactive<Record<number, boolean>>({
  1: false,
  2: false
})

const getCurrentTreeMenuIds = () => {
  if (!treeRef.value) return []
  return Array.from(new Set([
    ...(treeRef.value.getCheckedKeys(false) as Array<number>),
    ...(treeRef.value.getHalfCheckedKeys() as Array<number>)
  ]))
}

const saveCurrentClientMenuIds = () => {
  if (!dialogVisible.value) return
  roleMenuIdsByClientType[currentTreeClientType.value] = getCurrentTreeMenuIds()
}

const ensureRoleMenuIdsLoaded = async (roleId: number, clientType: number) => {
  if (loadedClientTypes[clientType]) return
  roleMenuIdsByClientType[clientType] = await PermissionApi.getRoleMenuList(roleId, clientType)
  loadedClientTypes[clientType] = true
}

const loadRoleMenus = async (roleId: number) => {
  currentTreeClientType.value = activeClientType.value
  treeNodeAll.value = false
  menuExpand.value = false
  treeRef.value?.setCheckedNodes([])
  menuOptions.value = handleTree(await MenuApi.getSimpleMenusList(currentTreeClientType.value))
  await ensureRoleMenuIdsLoaded(roleId, currentTreeClientType.value)
  await nextTick()
  formData.menuIds = roleMenuIdsByClientType[currentTreeClientType.value] ?? []
  formData.menuIds.forEach((menuId: number) => {
    treeRef.value.setChecked(menuId, true, false)
  })
}

/** 打开弹窗 */
const open = async (row: RoleApi.RoleVO) => {
  dialogVisible.value = true
  resetForm()
  // 设置数据
  formData.id = row.id
  formData.name = row.name
  formData.code = row.code
  formLoading.value = true
  try {
    await loadRoleMenus(row.id)
  } finally {
    formLoading.value = false
  }
}
defineExpose({ open }) // 提供 open 方法，用于打开弹窗

/** 切换客户端类型 */
const handleClientTypeChange = async (val: number | string) => {
  saveCurrentClientMenuIds()
  activeClientType.value = Number(val)
  if (!dialogVisible.value || !formData.id) return
  formLoading.value = true
  try {
    await loadRoleMenus(formData.id)
  } finally {
    formLoading.value = false
  }
}

/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件，用于操作成功后的回调
const submitForm = async () => {
  // 校验表单
  if (!formRef) return
  const valid = await formRef.value.validate()
  if (!valid) return
  if (formData.id === undefined) return
  saveCurrentClientMenuIds()
  // 提交请求
  formLoading.value = true
  try {
    await Promise.all([1, 2].map((clientType) => ensureRoleMenuIdsLoaded(formData.id as number, clientType)))
    const data = {
      roleId: formData.id,
      menuIds: Array.from(new Set([
        ...roleMenuIdsByClientType[1],
        ...roleMenuIdsByClientType[2]
      ]))
    }
    await PermissionApi.assignRoleMenu(data)
    message.success(t('common.updateSuccess'))
    dialogVisible.value = false
    // 发送操作成功的事件
    emit('success')
  } finally {
    formLoading.value = false
  }
}

/** 重置表单 */
const resetForm = () => {
  // 重置选项
  activeClientType.value = 1
  currentTreeClientType.value = 1
  treeNodeAll.value = false
  menuExpand.value = false
  // 重置表单
  formData.id = undefined
  formData.name = ''
  formData.code = ''
  formData.menuIds = []
  roleMenuIdsByClientType[1] = []
  roleMenuIdsByClientType[2] = []
  loadedClientTypes[1] = false
  loadedClientTypes[2] = false
  treeRef.value?.setCheckedNodes([])
  formRef.value?.resetFields()
}

/** 全选/全不选 */
const handleCheckedTreeNodeAll = () => {
  treeRef.value.setCheckedNodes(treeNodeAll.value ? menuOptions.value : [])
}

/** 展开/折叠全部 */
const handleCheckedTreeExpand = () => {
  const nodes = treeRef.value?.store.nodesMap
  for (let node in nodes) {
    if (nodes[node].expanded === menuExpand.value) {
      continue
    }
    nodes[node].expanded = menuExpand.value
  }
}
</script>

<style scoped>
.role-permission-drawer :deep(.el-drawer__body) {
  padding: 0;
  overflow: hidden;
}

.role-permission-drawer__shell {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--el-bg-color);
}

.role-permission-drawer__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex: 0 0 74px;
  padding: 0 24px 0 16px;
  box-sizing: border-box;
  border-bottom: 1px solid var(--el-border-color-lighter);
}

.role-permission-drawer__title {
  display: flex;
  align-items: center;
  min-width: 0;
  color: var(--el-text-color-primary);
  font-size: 16px;
  font-weight: 600;
}

.role-permission-drawer__close {
  margin-right: 10px;
  color: var(--el-text-color-secondary);
}

.role-permission-drawer__body {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 24px 18px 92px;
  box-sizing: border-box;
}

.role-permission-drawer__footer {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 2;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 14px 18px;
  box-sizing: border-box;
  border-top: 1px solid var(--el-border-color-lighter);
  background: var(--el-bg-color);
}

.role-assign-menu-form :deep(.el-form-item__label) {
  min-width: 80px;
}

.role-assign-menu-form__meta-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 16px;
  margin-bottom: 16px;
}

.role-assign-menu-form__meta {
  margin-bottom: 0;
}

.role-assign-menu-form__meta :deep(.el-form-item__content) {
  min-width: 0;
}

.role-assign-menu-form__meta :deep(.el-tag) {
  max-width: 100%;
  height: 28px;
  overflow: hidden;
  border-color: var(--el-border-color-lighter);
  background: var(--el-fill-color-extra-light);
  color: var(--el-text-color-primary);
  line-height: 26px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.role-assign-menu-form__permission {
  margin-top: 6px;
  margin-bottom: 0;
}

.role-permission-tree-panel {
  width: 100%;
}

.role-permission-tree-panel__title {
  margin-bottom: 22px;
  color: var(--el-text-color-primary);
  font-size: 16px;
  line-height: 24px;
}

.role-assign-menu-form__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 12px;
}

.role-assign-menu-form__header :deep(.el-tabs__header) {
  margin: 0;
}

.role-assign-menu-form__header :deep(.el-tabs__nav-wrap::after) {
  display: none;
}

.role-assign-menu-form__actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.role-permission-tree {
  --el-tree-node-hover-bg-color: transparent;
  color: var(--el-text-color-primary);
  font-size: 14px;
}

.role-permission-tree :deep(.el-tree-node__content) {
  height: 28px;
  padding-right: 8px;
}

.role-permission-tree :deep(.el-tree-node__expand-icon) {
  color: var(--el-text-color-primary);
  font-size: 12px;
}

.role-permission-tree :deep(.el-checkbox) {
  height: 18px;
  margin-right: 8px;
}

.role-permission-tree :deep(.el-checkbox__inner) {
  width: 16px;
  height: 16px;
  border-radius: 4px;
}

.role-permission-tree :deep(.el-tree-node__label) {
  line-height: 22px;
}

@media (max-width: 768px) {
  .role-permission-drawer :deep(.el-drawer) {
    width: 100% !important;
  }

  .role-permission-drawer__header {
    padding-right: 14px;
  }

  .role-permission-drawer__body {
    padding-right: 14px;
    padding-left: 14px;
  }

  .role-assign-menu-form__meta-row {
    grid-template-columns: 1fr;
  }
}
</style>
