<template>
  <ElDialog
    v-model="visible"
    title="模板权限分配"
    width="1000px"
    align-center
    class="permission-dialog"
    @close="handleClose"
  >
    <div v-loading="loading" class="permission-container flex h-[65vh]">
      <!-- 左侧：一级模块导航 -->
      <div class="module-nav w-[200px] border-r border-gray-100 pr-2">
        <ElScrollbar>
          <div
            v-for="item in permissionTree"
            :key="item.id"
            :class="['nav-item', activeModuleId === item.id ? 'active' : '']"
            @click="activeModuleId = item.id"
          >
            <span class="truncate">{{ item.name }}</span>
            <ElTag
              v-if="getModuleSelectedCount(item) > 0"
              size="small"
              round
              effect="light"
              class="ml-auto"
            >
              {{ getModuleSelectedCount(item) }}
            </ElTag>
          </div>
        </ElScrollbar>
      </div>

      <!-- 右侧：权限点展示区 -->
      <div class="module-content flex-1 pl-6 overflow-hidden flex flex-col">
        <div v-if="activeModule" class="flex items-center justify-between mb-4 pb-2 border-b">
          <div class="flex items-center gap-2">
            <h3 class="text-lg font-bold">{{ activeModule.name }}</h3>
            <span class="text-xs text-gray-400">请勾选该模块下的操作权限</span>
          </div>
          <div class="flex items-center gap-4">
            <ElCheckbox
              :model-value="isModuleAllSelected(activeModule)"
              :indeterminate="isModuleIndeterminate(activeModule)"
              @change="(val) => handleSelectAllModule(activeModule, !!val)"
            >
              全选当前模块
            </ElCheckbox>
          </div>
        </div>

        <ElScrollbar v-if="activeModule" class="flex-1">
          <div v-for="sub in activeModule.children" :key="sub.id" class="sub-module mb-6">
            <div class="flex items-center gap-2 mb-3">
              <div class="w-1 h-4 bg-primary rounded-full"></div>
              <span class="font-bold">{{ sub.name }}</span>
              <ElCheckbox
                size="small"
                :model-value="isSubModuleAllSelected(sub)"
                :indeterminate="isSubModuleIndeterminate(sub)"
                class="ml-4"
                @change="(val) => handleSelectSubModule(sub, !!val)"
              >
                全选
              </ElCheckbox>
            </div>

            <!-- 权限点平铺 -->
            <div class="grid grid-cols-2 lg:grid-cols-3 gap-3 pl-3">
              <div
                v-for="perm in sub.children"
                :key="perm.code"
                class="perm-item p-2 rounded hover:bg-gray-50 border border-transparent hover:border-gray-100 transition-all"
                :class="{ 'bg-blue-50/50 border-blue-100': isChecked(perm.code) }"
                @click="togglePermission(perm.code)"
              >
                <div class="flex items-start gap-2">
                  <ElCheckbox
                    :model-value="isChecked(perm.code)"
                    @update:model-value="togglePermission(perm.code)"
                    @click.stop
                  />
                  <div class="flex flex-col gap-0.5">
                    <div class="flex items-center gap-1">
                      <ElTag size="small" :type="getPermissionTagType(perm.code)" effect="plain">
                        {{ getPermissionAction(perm.code) }}
                      </ElTag>
                      <span class="text-sm font-medium leading-tight">{{ perm.name }}</span>
                    </div>
                    <span v-if="perm.description" class="text-[11px] text-gray-400 leading-tight">
                      {{ perm.description }}
                    </span>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </ElScrollbar>

        <div v-else class="flex flex-col items-center justify-center h-full text-gray-400">
          <ElIcon :size="48"><Collection /></ElIcon>
          <p class="mt-2">请选择左侧模块进行权限配置</p>
        </div>
      </div>
    </div>

    <template #footer>
      <div class="flex items-center justify-between w-full">
        <div class="text-sm text-gray-500">
          已选择 <span class="text-primary font-bold">{{ checkedKeys.length }}</span> 项权限
        </div>
        <div class="flex gap-2">
          <ElButton @click="handleClose">取消</ElButton>
          <ElButton type="primary" :loading="saving" @click="savePermission">保存更改</ElButton>
        </div>
      </div>
    </template>
  </ElDialog>
</template>

<script setup lang="ts">
  import { ref, computed, watch } from 'vue'
  import {
    fetchGetRoleTemplateDetail,
    fetchUpdateRoleTemplate,
    fetchGetRoleTemplatePermissions
  } from '@/api/role-template'
  import { fetchGetPermissionTree } from '@/api/permission'
  import { ElMessage, ElTag } from 'element-plus'
  import { Collection } from '@element-plus/icons-vue'

  interface Props {
    modelValue: boolean
    templateData?: Api.RoleTemplate.RoleTemplateDto
  }

  interface Emits {
    (e: 'update:modelValue', value: boolean): void
    (e: 'success'): void
  }

  const props = withDefaults(defineProps<Props>(), {
    modelValue: false,
    templateData: undefined
  })

  const emit = defineEmits<Emits>()

  const loading = ref(false)
  const saving = ref(false)
  const checkedKeys = ref<string[]>([])
  const permissionTree = ref<any[]>([])
  const activeModuleId = ref<string | number>('')

  // Full template data needed for update
  const fullTemplateData = ref<Api.RoleTemplate.RoleTemplateDto | null>(null)

  const visible = computed({
    get: () => props.modelValue,
    set: (value) => emit('update:modelValue', value)
  })

  const activeModule = computed(() => {
    return permissionTree.value.find((m) => m.id === activeModuleId.value)
  })

  // Helper for tag styling
  const getPermissionTagType = (code: string) => {
    if (!code) return 'info'
    const lower = code.toLowerCase()
    if (lower.includes('create') || lower.includes('add')) return 'primary'
    if (
      lower.includes('read') ||
      lower.includes('get') ||
      lower.includes('list') ||
      lower.includes('view')
    )
      return 'success'
    if (lower.includes('update') || lower.includes('edit') || lower.includes('modify'))
      return 'warning'
    if (lower.includes('delete') || lower.includes('remove')) return 'danger'
    return 'info'
  }

  const getPermissionAction = (code: string) => {
    if (!code) return '权限'
    const parts = code.split(':')
    const last = parts[parts.length - 1]
    // 映射一些常见动作为中文，如果需要的话
    const actionMap: Record<string, string> = {
      read: '查看',
      create: '新增',
      update: '修改',
      delete: '删除',
      export: '导出',
      import: '导入',
      audit: '审核'
    }
    return actionMap[last] || last
  }

  // 获取模块选中的数量
  const getModuleSelectedCount = (module: any) => {
    let count = 0
    const traverse = (items: any[]) => {
      items.forEach((item) => {
        if (!item.children || item.children.length === 0) {
          if (checkedKeys.value.includes(item.code)) count++
        } else {
          traverse(item.children)
        }
      })
    }
    if (module.children) traverse(module.children)
    return count
  }

  const isChecked = (code: string) => checkedKeys.value.includes(code)

  const togglePermission = (code: string) => {
    const index = checkedKeys.value.indexOf(code)
    if (index > -1) {
      checkedKeys.value.splice(index, 1)
    } else {
      checkedKeys.value.push(code)
    }
  }

  // 处理子模块（二级）全选
  const handleSelectSubModule = (sub: any, selected: boolean) => {
    const codes: string[] = []
    const traverse = (items: any[]) => {
      items.forEach((item) => {
        if (!item.children || item.children.length === 0) {
          if (item.code) codes.push(item.code)
        } else {
          traverse(item.children)
        }
      })
    }
    traverse(sub.children || [])

    codes.forEach((code) => {
      const idx = checkedKeys.value.indexOf(code)
      if (selected && idx === -1) checkedKeys.value.push(code)
      if (!selected && idx > -1) checkedKeys.value.splice(idx, 1)
    })
  }

  const isSubModuleAllSelected = (sub: any) => {
    const codes: string[] = []
    const traverse = (items: any[]) => {
      items.forEach((item) => {
        if (!item.children || item.children.length === 0) {
          if (item.code) codes.push(item.code)
        } else {
          traverse(item.children)
        }
      })
    }
    traverse(sub.children || [])
    return codes.length > 0 && codes.every((code) => checkedKeys.value.includes(code))
  }

  const isSubModuleIndeterminate = (sub: any) => {
    const codes: string[] = []
    const traverse = (items: any[]) => {
      items.forEach((item) => {
        if (!item.children || item.children.length === 0) {
          if (item.code) codes.push(item.code)
        } else {
          traverse(item.children)
        }
      })
    }
    traverse(sub.children || [])
    const checkedCount = codes.filter((code) => checkedKeys.value.includes(code)).length
    return checkedCount > 0 && checkedCount < codes.length
  }

  // 处理主模块（一级）全选
  const handleSelectAllModule = (module: any, selected: boolean) => {
    module.children?.forEach((sub: any) => handleSelectSubModule(sub, selected))
  }

  const isModuleAllSelected = (module: any) => {
    return module.children?.every((sub: any) => isSubModuleAllSelected(sub))
  }

  const isModuleIndeterminate = (module: any) => {
    if (isModuleAllSelected(module)) return false
    return module.children?.some(
      (sub: any) => isSubModuleIndeterminate(sub) || isSubModuleAllSelected(sub)
    )
  }

  // 列表转树形结构
  const listToTree = (list: any[]): any[] => {
    const map = new Map<string, any>()
    const roots: any[] = []

    list.forEach((item) => {
      const node = { ...item, children: [] }
      map.set(item.id, node)
    })

    list.forEach((item) => {
      const node = map.get(item.id)
      if (item.parentId && map.has(item.parentId)) {
        map.get(item.parentId).children.push(node)
      } else {
        roots.push(node)
      }
    })
    return roots
  }

  watch(
    () => props.modelValue,
    async (val) => {
      if (val && props.templateData) {
        loading.value = true
        try {
          const [treeRes, detailRes, assignedPermsRes] = await Promise.all([
            fetchGetPermissionTree(),
            fetchGetRoleTemplateDetail(props.templateData.templateCode),
            fetchGetRoleTemplatePermissions(props.templateData.templateCode)
          ])

          // 处理树数据
          if (treeRes && treeRes.length > 0) {
            const hasChildren = treeRes.some((item: any) => item.children && item.children.length)
            const rawTree = hasChildren ? treeRes : listToTree(treeRes)

            // 深度优先遍历，提取所有真正的权限点（叶子节点）并按其“父路径”分组
            permissionTree.value = rawTree.map((module: any) => {
              const subModulesMap = new Map<string, any>()

              const collectPermissions = (node: any, parentName: string) => {
                const isLeaf = !node.children || node.children.length === 0

                if (isLeaf) {
                  // 它是权限点，放入当前父级名称对应的组中
                  if (!subModulesMap.has(parentName)) {
                    subModulesMap.set(parentName, {
                      id: `group-${parentName}-${module.id}`,
                      name: parentName,
                      children: []
                    })
                  }
                  subModulesMap.get(parentName).children.push(node)
                } else {
                  // 它是中间层（目录/菜单），继续向下找，并更新父级名称
                  node.children.forEach((child: any) => {
                    collectPermissions(child, node.name)
                  })
                }
              }

              // 如果顶级模块直接有权限点（即 children 中有叶子），它们会被归类到以“模块名”命名的组下
              module.children?.forEach((child: any) => {
                collectPermissions(child, child.children?.length ? child.name : module.name)
              })

              return {
                ...module,
                children: Array.from(subModulesMap.values())
              }
            })

            if (permissionTree.value.length > 0) {
              activeModuleId.value = permissionTree.value[0].id
            }
          }

          fullTemplateData.value = detailRes
          const assignedCodes = assignedPermsRes.map((p: any) => p.code || p.permissionCode)
          checkedKeys.value = [...assignedCodes]
        } catch (error) {
          void error
          ElMessage.error('加载数据失败')
        } finally {
          loading.value = false
        }
      }
    }
  )

  const savePermission = async () => {
    if (!fullTemplateData.value) return

    saving.value = true
    try {
      await fetchUpdateRoleTemplate(fullTemplateData.value.templateCode, {
        templateCode: fullTemplateData.value.templateCode,
        name: fullTemplateData.value.name,
        description: fullTemplateData.value.description,
        isActive: fullTemplateData.value.isActive,
        permissionCodes: checkedKeys.value
      })
      ElMessage.success('权限保存成功')
      emit('success')
      visible.value = false
    } catch (error) {
      void error
      ElMessage.error('保存失败')
    } finally {
      saving.value = false
    }
  }

  const handleClose = () => {
    visible.value = false
  }
</script>

<style scoped lang="scss">
  .permission-dialog {
    :deep(.el-dialog__body) {
      padding: 0;
      border-top: 1px solid var(--el-border-color-lighter);
      border-bottom: 1px solid var(--el-border-color-lighter);
    }
  }

  .nav-item {
    display: flex;
    align-items: center;
    padding: 12px 16px;
    margin-bottom: 4px;
    font-size: 14px;
    color: var(--el-text-color-regular);
    cursor: pointer;
    border-radius: 6px;
    transition: all 0.2s;

    &:hover {
      background-color: var(--el-fill-color-light);
    }

    &.active {
      font-weight: bold;
      color: var(--el-color-primary);
      background-color: var(--el-color-primary-light-9);
    }
  }

  .perm-item {
    cursor: pointer;
    user-select: none;
  }
</style>
