<template>
  <Dialog v-model="dialogVisible" title="web端角色路由配置" width="1200">
    <el-form ref="formRef" v-loading="formLoading" :model="formData" label-width="120px">
      <el-row :gutter="20">
        <el-col :span="12">
          <el-form-item label="角色名称">
            <el-tag>{{ formData.name }}</el-tag>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="角色标识">
            <el-tag>{{ formData.code }}</el-tag>
          </el-form-item>
        </el-col>
      </el-row>

      <el-divider content-position="left">web路由数据权限</el-divider>
      <br/>

      <!-- 字典数据选择 -->
      <el-form-item label="路由类型">
        <el-checkbox-group v-model="formData.dataScopeWebRoute" size="large">
          <el-checkbox-button v-for="dict in routeTypeOptions" :key="dict.value" :label="dict.value">
            {{ dict.label }}
          </el-checkbox-button>
        </el-checkbox-group>
      </el-form-item>

      <!-- 标签页 -->
      <el-tabs v-model="activeTab" type="border-card">
        <!-- 课程权限 -->
        <el-tab-pane label="课程权限" name="course">
          <el-row :gutter="20">
            <el-col :span="12">
              <!-- 通识课权限 -->
              <el-form-item label="通识课">
                <el-card class="w-full h-300px !overflow-y-scroll" shadow="never">
                  <template #header>
                    全选/全不选:
                    <el-switch
                      v-model="courseTabs.generalTreeNodeAll"
                      active-text="是"
                      inactive-text="否"
                      inline-prompt
                      @change="handleCheckedTreeNodeAll('course', 'general')"
                    />
                    全部展开/折叠:
                    <el-switch
                      v-model="courseTabs.generalDeptExpand"
                      active-text="展开"
                      inactive-text="折叠"
                      inline-prompt
                      @change="handleCheckedTreeExpand('course', 'general')"
                    />
                    父子联动:
                    <el-switch v-model="courseTabs.generalCheckStrictly" active-text="是" inactive-text="否" inline-prompt />
                  </template>
                  <el-tree
                    ref="generalTreeRef"
                    :check-strictly="!courseTabs.generalCheckStrictly"
                    :data="courseTabs.generalCourseOptions"
                    :props="defaultProps"
                    default-expand-all
                    empty-text="加载中，请稍后"
                    node-key="id"
                    show-checkbox
                  />
                </el-card>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <!-- 实操课权限 -->
              <el-form-item label="实操课">
                <el-card class="w-full h-300px !overflow-y-scroll" shadow="never">
                  <template #header>
                    全选/全不选:
                    <el-switch
                      v-model="courseTabs.practicalTreeNodeAll"
                      active-text="是"
                      inactive-text="否"
                      inline-prompt
                      @change="handleCheckedTreeNodeAll('course', 'practical')"
                    />
                    全部展开/折叠:
                    <el-switch
                      v-model="courseTabs.practicalDeptExpand"
                      active-text="展开"
                      inactive-text="折叠"
                      inline-prompt
                      @change="handleCheckedTreeExpand('course', 'practical')"
                    />
                    父子联动:
                    <el-switch v-model="courseTabs.practicalCheckStrictly" active-text="是" inactive-text="否" inline-prompt />
                  </template>
                  <el-tree
                    ref="practicalTreeRef"
                    :check-strictly="!courseTabs.practicalCheckStrictly"
                    :data="courseTabs.practicalCourseOptions"
                    :props="defaultProps"
                    default-expand-all
                    empty-text="加载中，请稍后"
                    node-key="id"
                    show-checkbox
                  />
                </el-card>
              </el-form-item>
            </el-col>
          </el-row>
        </el-tab-pane>

        <!-- blockly课程权限 -->
        <el-tab-pane label="blockly课程权限" name="blockly">
          <el-form-item label="blockly课程权限">
            <el-card class="w-full h-300px !overflow-y-scroll" shadow="never">
              <template #header>
                全选/全不选:
                <el-switch
                  v-model="blocklyTabs.generalTreeNodeAll"
                  active-text="是"
                  inactive-text="否"
                  inline-prompt
                  @change="handleCheckedTreeNodeAll('blockly', 'general')"
                />
                全部展开/折叠:
                <el-switch
                  v-model="blocklyTabs.generalDeptExpand"
                  active-text="展开"
                  inactive-text="折叠"
                  inline-prompt
                  @change="handleCheckedTreeExpand('blockly', 'general')"
                />
                父子联动:
                <el-switch v-model="blocklyTabs.generalCheckStrictly" active-text="是" inactive-text="否" inline-prompt />
              </template>
              <el-tree
                ref="blocklyTreeRef"
                :check-strictly="!blocklyTabs.generalCheckStrictly"
                :data="blocklyTabs.generalBlocklyOptions"
                :props="defaultProps"
                default-expand-all
                empty-text="加载中，请稍后"
                node-key="id"
                show-checkbox
              />
            </el-card>
          </el-form-item>
        </el-tab-pane>

        <!-- AI实验课权限 -->
        <el-tab-pane label="AI实验课权限" name="aiCourse">
          <el-form-item label="AI实验课权限">
            <el-card class="w-full h-300px !overflow-y-scroll" shadow="never">
              <template #header>
                全选/全不选:
                <el-switch
                  v-model="aiCourseTabs.generalTreeNodeAll"
                  active-text="是"
                  inactive-text="否"
                  inline-prompt
                  @change="handleCheckedTreeNodeAll('aiCourse', 'general')"
                />
                全部展开/折叠:
                <el-switch
                  v-model="aiCourseTabs.generalDeptExpand"
                  active-text="展开"
                  inactive-text="折叠"
                  inline-prompt
                  @change="handleCheckedTreeExpand('aiCourse', 'general')"
                />
                父子联动:
                <el-switch v-model="aiCourseTabs.generalCheckStrictly" active-text="是" inactive-text="否" inline-prompt />
              </template>
              <el-tree
                ref="aiCourseTreeRef"
                :check-strictly="!aiCourseTabs.generalCheckStrictly"
                :data="aiCourseTabs.generalAiCourseOptions"
                :props="defaultProps"
                default-expand-all
                empty-text="加载中，请稍后"
                node-key="id"
                show-checkbox
              />
            </el-card>
          </el-form-item>
        </el-tab-pane>
      </el-tabs>
    </el-form>

    <template #footer>
      <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
      <el-button @click="dialogVisible = false">取 消</el-button>
    </template>
  </Dialog>
</template>
<script lang="ts" setup>
import { defaultProps } from '@/utils/tree'
import { DICT_TYPE, getDictOptions } from '@/utils/dict'
import * as RoleApi from '@/api/system/role'
import { CourseApi } from '@/api/bjdx/course'
import { AiCourseTypeApi } from '@/api/aiCourse/aiCourseType'
import { BlocklyTypeApi } from '@/api/blockly/blocklyType'
import * as PermissionApi from '@/api/system/permission'

defineOptions({ name: 'SystemRoleWebPermissionForm' })

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

const dialogVisible = ref(false) // 弹窗的是否展示
const formLoading = ref(false) // 表单的加载中：1）修改时的数据加载；2）提交的按钮禁用
const activeTab = ref('course') // 当前激活的标签页
const routeTypeOptions = ref(getDictOptions(DICT_TYPE.WEB_ROLE_ROUTE)) // 路由类型字典选项
console.log('routeTypeOptions', routeTypeOptions)
const formData = reactive({
  id: undefined,
  name: '',
  code: '',
  dataScopeCourseIds: [],
  dataScopeAiCourseIds: [],
  dataScopeBlocklyIds: [],
  dataScopeWebRoute: []
})
const formRef = ref() // 表单 Ref

// 课程权限相关变量
const generalTreeRef = ref() // 通识课菜单树组件 Ref
const practicalTreeRef = ref() // 实操课菜单树组件 Ref
const courseTabs = reactive({
  generalCourseOptions: [] as any[], // 通识课树形结构
  generalDeptExpand: true, // 通识课展开/折叠
  generalTreeNodeAll: false, // 通识课全选/全不选
  generalCheckStrictly: true, // 通识课是否严格模式
  practicalCourseOptions: [] as any[], // 实操课树形结构
  practicalDeptExpand: true, // 实操课展开/折叠
  practicalTreeNodeAll: false, // 实操课全选/全不选
  practicalCheckStrictly: true, // 实操课是否严格模式
})

// AI实验课权限相关变量
const aiCourseTreeRef = ref() // AI实验课菜单树组件 Ref
const aiCourseTabs = reactive({
  generalAiCourseOptions: [] as any[], // AI实验课树形结构
  generalDeptExpand: true, // AI实验课展开/折叠
  generalTreeNodeAll: false, // AI实验课全选/全不选
  generalCheckStrictly: true, // AI实验课是否严格模式
})

// blockly课程权限相关变量
const blocklyTreeRef = ref() // blockly课程菜单树组件 Ref
const blocklyTabs = reactive({
  generalBlocklyOptions: [] as any[], // blockly课程树形结构
  generalDeptExpand: true, // blockly课程展开/折叠
  generalTreeNodeAll: false, // blockly课程全选/全不选
  generalCheckStrictly: true, // blockly课程是否严格模式
})

/** 打开弹窗 */
const open = async (row: RoleApi.RoleVO) => {
  dialogVisible.value = true
  resetForm()

  // 设置数据
  formData.id = row.id
  formData.name = row.name
  formData.code = row.code
  formData.dataScopeWebRoute = row.dataScopeWebRoute || []
  // formData.dataScopeWebRoute = ["course","aiCourse","blockly"]

  // 加载各类型数据
  await Promise.all([
    loadCourseData(row),
    loadAiCourseData(row),
    loadBlocklyData(row)
  ])
  
  await nextTick()
  
    // 兼容旧数据格式
    // if (formData.dataScopeWebRoute.length === 0) {
    //   if (row.dataScopeCourseIds && row.dataScopeCourseIds.length > 0) {
    //     formData.dataScopeWebRoute.push('course')
    //   }
    //   if (row.dataScopeAiCourseIds && row.dataScopeAiCourseIds.length > 0) {
    //     formData.dataScopeWebRoute.push('aiCourse')
    //   }
    //   if (row.dataScopeBlocklyIds && row.dataScopeBlocklyIds.length > 0) {
    //     formData.dataScopeWebRoute.push('blockly')
    //   }
    // }
  
  // 默认选择第一个可用的标签页
  if (formData.dataScopeWebRoute.length > 0) {
    activeTab.value = formData.dataScopeWebRoute[0]
  }
}

defineExpose({ open }) // 提供 open 方法，用于打开弹窗

/** 加载课程数据 */
async function loadCourseData(row: RoleApi.RoleVO) {
  const allCourses = await CourseApi.getCourseTypeTree()

  courseTabs.generalCourseOptions = filterCoursesByType(allCourses, '通识课')
  courseTabs.practicalCourseOptions = filterCoursesByType(allCourses, '实操课')

  await nextTick()

  // 设置选中状态
  if (row.dataScopeCourseIds && row.dataScopeCourseIds.length > 0) {
    row.dataScopeCourseIds.forEach((courseId: number): void => {
      generalTreeRef.value?.setChecked(courseId * 100, true, false)
      practicalTreeRef.value?.setChecked(courseId * 100, true, false)
    })
  }

}

/** 加载AI实验课数据 */
async function loadAiCourseData(row: RoleApi.RoleVO) {
  const allCourses = await AiCourseTypeApi.getAiCourseTypeTree()
  aiCourseTabs.generalAiCourseOptions = filterCoursesByType(allCourses, "aiCourseType")

  await nextTick()

  // 设置选中状态
  if (row.dataScopeAiCourseIds && row.dataScopeAiCourseIds.length > 0) {
    row.dataScopeAiCourseIds.forEach((courseId: number): void => {
      aiCourseTreeRef.value?.setChecked(courseId, true, false)
    })
  }
}

/** 加载blockly课程数据 */
async function loadBlocklyData(row: RoleApi.RoleVO) {
  const allCourses = await BlocklyTypeApi.getBlocklyTypeTree()
  blocklyTabs.generalBlocklyOptions = filterCoursesByType(allCourses, "blocklyType")

  await nextTick()

  // 设置选中状态
  if (row.dataScopeBlocklyIds && row.dataScopeBlocklyIds.length > 0) {
    row.dataScopeBlocklyIds.forEach((courseId: number): void => {
      blocklyTreeRef.value?.setChecked(courseId, true, false)
    })
  }
}

/**
 * 根据课程类型筛选课程，并保留完整的树结构
 * @param courses 原始课程树数据
 * @param type 课程类型
 * @returns 筛选后的课程树数据
 */
function filterCoursesByType(courses: any[], type: string): any[] {
  // 深拷贝原始数据，避免修改原始数组
  const filteredCourses = JSON.parse(JSON.stringify(courses))

  // 递归处理树结构，只保留指定类型的节点及其父节点
  function filterTreeNodes(nodes: any[]): any[] {
    return nodes
      .map(node => {
        // 复制当前节点
        const newNode = { ...node }

        // 递归处理子节点
        if (node.children && node.children.length > 0) {
          const filteredChildren = filterTreeNodes(node.children)
          if (filteredChildren.length > 0) {
            newNode.children = filteredChildren
            return newNode
          }
        }

        // 如果当前节点是指定类型，或者有符合条件的子节点，则保留
        if (node.type === type) {
          return newNode
        }

        return null
      })
      .filter(node => node !== null)
  }

  return filterTreeNodes(filteredCourses)
}

/** 提交表单 */
const emit = defineEmits(['success'])
const submitForm = async () => {
  formLoading.value = true
  try {
    const data: any = {
      roleId: formData.id,
      dataScopeWebRoute: formData.dataScopeWebRoute
    }

    // 处理课程权限
    const generalCheckedKeys = generalTreeRef.value?.getCheckedKeys(false) || []
    const practicalCheckedKeys = practicalTreeRef.value?.getCheckedKeys(false) || []
    const allCheckedKeys = [...generalCheckedKeys, ...practicalCheckedKeys]
    const allCourseOptions = [...courseTabs.generalCourseOptions, ...courseTabs.practicalCourseOptions]
    // 课程类型的叶子节点类型是'通识课'或'实操课'，所以不需要过滤叶子节点类型
    data.dataScopeCourseIds = allCheckedKeys.filter(key => {
      // 只保留实际存在于树结构中的节点ID
      const nodeMap = new Map<number, boolean>()
      function traverseTree(nodes: any[]) {
        nodes.forEach(node => {
          nodeMap.set(node.id, true)
          if (node.children && node.children.length > 0) {
            traverseTree(node.children)
          }
        })
      }
      traverseTree(allCourseOptions)
      return nodeMap.has(key)
    })

    // 处理AI实验课权限
    const aiCourseCheckedKeys = aiCourseTreeRef.value?.getCheckedKeys(false) || []
    data.dataScopeAiCourseIds = filterChildNodeKeys(aiCourseCheckedKeys, aiCourseTabs.generalAiCourseOptions, "aiCourseType")

    // 处理blockly课程权限
    const blocklyCheckedKeys = blocklyTreeRef.value?.getCheckedKeys(false) || []
    data.dataScopeBlocklyIds = filterChildNodeKeys(blocklyCheckedKeys, blocklyTabs.generalBlocklyOptions, "blocklyType")

    console.log('提交的数据:', data)
    await PermissionApi.assignRoleWebScope(data)
    message.success(t('common.updateSuccess'))
    dialogVisible.value = false
    // 发送操作成功的事件
    emit('success')
  } finally {
    formLoading.value = false
  }
}

/**
 * 过滤只包含子节点的ID
 * @param checkedKeys 所有选中的节点ID
 * @param treeData 树结构数据
 * @param leafType 叶子节点类型
 * @returns 只包含子节点的ID数组
 */
function filterChildNodeKeys(checkedKeys: number[], treeData: any[], leafType: string): number[] {
  // 创建一个Map存储所有节点ID及其是否为叶子节点的状态
  const nodeMap = new Map<number, boolean>()

  // 递归遍历树结构，标记每个节点是否为叶子节点
  function traverseTree(nodes: any[]) {
    nodes.forEach(node => {
      nodeMap.set(node.id, node.type === leafType)

      // 递归处理子节点
      if (node.children && node.children.length > 0) {
        traverseTree(node.children)
      }
    })
  }

  // 执行遍历
  traverseTree(treeData)

  // 过滤出只包含叶子节点的ID
  return checkedKeys.filter(key => {
    // 如果节点存在于nodeMap中且是叶子节点，则保留
    return nodeMap.has(key) && nodeMap.get(key)
  })
}

/** 重置表单 */
const resetForm = () => {

  // 重置课程权限选项
  courseTabs.generalCourseOptions = []
  courseTabs.generalDeptExpand = true
  courseTabs.generalTreeNodeAll = false
  courseTabs.generalCheckStrictly = true
  generalTreeRef.value?.setCheckedNodes([])

  courseTabs.practicalCourseOptions = []
  courseTabs.practicalDeptExpand = true
  courseTabs.practicalTreeNodeAll = false
  courseTabs.practicalCheckStrictly = true
  practicalTreeRef.value?.setCheckedNodes([])

  // 重置AI实验课选项
  aiCourseTabs.generalAiCourseOptions = []
  aiCourseTabs.generalDeptExpand = true
  aiCourseTabs.generalTreeNodeAll = false
  aiCourseTabs.generalCheckStrictly = true
  aiCourseTreeRef.value?.setCheckedNodes([])

  // 重置blockly课程选项
  blocklyTabs.generalBlocklyOptions = []
  blocklyTabs.generalDeptExpand = true
  blocklyTabs.generalTreeNodeAll = false
  blocklyTabs.generalCheckStrictly = true
  blocklyTreeRef.value?.setCheckedNodes([])

  // 重置表单数据
    formData.id = undefined
    formData.name = ''
    formData.code = ''
    formData.dataScopeCourseIds = []
    formData.dataScopeAiCourseIds = []
    formData.dataScopeBlocklyIds = []
    formData.dataScopeWebRoute = []

    formRef.value?.resetFields()
}

/** 处理全选/全不选 */
function handleCheckedTreeNodeAll(tabType: string, treeType: string) {
  if (tabType === 'course') {
    if (treeType === 'general') {
      generalTreeRef.value?.setCheckedNodes(courseTabs.generalTreeNodeAll ? courseTabs.generalCourseOptions : [])
    } else if (treeType === 'practical') {
      practicalTreeRef.value?.setCheckedNodes(courseTabs.practicalTreeNodeAll ? courseTabs.practicalCourseOptions : [])
    }
  } else if (tabType === 'aiCourse') {
    aiCourseTreeRef.value?.setCheckedNodes(aiCourseTabs.generalTreeNodeAll ? aiCourseTabs.generalAiCourseOptions : [])
  } else if (tabType === 'blockly') {
    blocklyTreeRef.value?.setCheckedNodes(blocklyTabs.generalTreeNodeAll ? blocklyTabs.generalBlocklyOptions : [])
  }
}

/** 处理展开/折叠全部 */
function handleCheckedTreeExpand(tabType: string, treeType: string) {
  if (tabType === 'course') {
    const treeRef = treeType === 'general' ? generalTreeRef.value : practicalTreeRef.value
    const expandValue = treeType === 'general' ? courseTabs.generalDeptExpand : courseTabs.practicalDeptExpand
    expandTreeNodes(treeRef, expandValue)
  } else if (tabType === 'aiCourse') {
    expandTreeNodes(aiCourseTreeRef.value, aiCourseTabs.generalDeptExpand)
  } else if (tabType === 'blockly') {
    expandTreeNodes(blocklyTreeRef.value, blocklyTabs.generalDeptExpand)
  }
}

/** 展开/折叠树节点 */
function expandTreeNodes(treeRef: any, expand: boolean) {
  const nodes = treeRef?.store.nodesMap
  if (nodes) {
    for (let node in nodes) {
      if (nodes[node].expanded === expand) {
        continue
      }
      nodes[node].expanded = expand
    }
  }
}
</script>
