<template>
  <basicModal
    @register="modalRegister"
    ref="modalRef"
    class="basicModal basicFormModal"
    @on-ok="handleSubmit"
    @on-close="handleClose"
  >
    <template #default>
      <div>
        <n-checkbox v-model:checked="expandFlag" @update:checked="handleExpand"
          >展开/折叠</n-checkbox
        >
        <n-checkbox v-model:checked="checkedFlag" @update:checked="handleSelectAll"
          >全选/不全选</n-checkbox
        >
        <div>
          <n-tree
            :data="menuTree"
            key-field="id"
            label-field="name"
            children-field="children"
            cascade
            virtual-scroll
            style="height: 450px"
            :checked-keys="checkedKeys"
            :expanded-keys="expandedKeys"
            :indeterminate-keys="halfCheckedIds"
            @update:checked-keys="onChangePermissionsTree"
            ref="treeRef"
            @update:expanded-keys="handleExpands"
            checkable
          />
        </div>
      </div>
    </template>
  </basicModal>
</template>
<script lang="ts" setup>
  import { getRoleMenuList, roleMenuSave } from '@/api/system/role';
  import { buildTree } from '@/utils/auth';
  import { useMessage } from 'naive-ui';
  import { onMounted, ref } from 'vue';
  import { useModal } from '@/components/Modal';

  /**
   * 定义接收的参数
   */
  const props = defineProps({
    visible: {
      type: Boolean,
      required: true,
      default: false,
    },
    roleId: {
      type: Number,
      required: true,
      default: 0,
    },
  });

  /**
   * 定义参数变量
   */
  const message = useMessage();
  const emit = defineEmits(['success', 'update:visible']);
  const treeRef = ref();
  const checkedFlag = ref(false);
  const expandFlag = ref(false);
  const allMenuIds = ref([]);
  const checkedKeys = ref([]);
  const halfCheckedIds = ref([]);
  const expandedKeys = ref([]);
  const menuArray = ref<any[]>([]);
  const menuTree = ref<any[]>([]);

  /**
   * 定义模态
   */
  const [modalRegister, { openModal, setSubLoading }] = useModal({
    title: '分配权限',
    subBtuText: '确定',
    width: 600,
  });

  /**
   * 执行扩展、收缩
   */
  const handleExpand = () => {
    if (expandFlag.value) {
      expandedKeys.value = allMenuIds.value;
    } else {
      expandedKeys.value = [];
    }
  };

  /**
   * 执行选中全部
   */
  const handleSelectAll = () => {
    if (checkedFlag.value) {
      checkedKeys.value = allMenuIds.value;
    } else {
      checkedKeys.value = [];
    }
  };

  /**
   * 获取所有选择的节点
   */
  const getDeptAllCheckedKeys = () => {
    const checkedKeys = treeRef.value?.getCheckedData().keys;
    const halfCheckedKeys = treeRef.value?.getIndeterminateData().keys;
    checkedKeys?.unshift.apply(checkedKeys, halfCheckedKeys);
    return checkedKeys;
  };

  /**
   * 执行提交表单
   */
  const handleSubmit = async () => {
    const keys = getDeptAllCheckedKeys()!;
    await roleMenuSave({ menuIds: keys, roleId: props.roleId });
    message.success('操作成功');
    emit('update:visible', false);
    emit('success');
  };

  /**
   * 关闭窗体
   */
  const handleClose = () => {
    emit('update:visible', false);
  };

  /**
   * 树结构选中发生变化
   * @param node 节点
   * @param event 事件
   */
  const onChangePermissionsTree = (node, event) => {
    checkedKeys.value = node;
  };

  /**
   * 执行收缩、展开
   * @param node 参数
   */
  const handleExpands = (node) => {
    expandedKeys.value = node;
  };

  /**
   * 设置表单数据
   */
  const setFormData = async () => {
    const data = await getRoleMenuList(props.roleId);
    menuTree.value = buildTree(data);
    menuArray.value = data;
    menuArray.value.map((item) => {
      allMenuIds.value.push(item.id);
    });
    const keys = checkTree(menuTree.value, 0, [], []);
    checkedKeys.value = keys.checkedIds;
    halfCheckedIds.value = keys.halfCheckedIds;
  };

  /**
   * 选中树结构
   * @param nodes 节点
   * @param parentId 上级ID
   * @param checkedIds 选中ID集合
   * @param halfCheckedIds
   */
  function checkTree(nodes, parentId = null, checkedIds, halfCheckedIds) {
    nodes.forEach((node) => {
      let allChildrenChecked = true;
      let someChildrenChecked = false;

      // 检查子节点
      if (node.children && node.children.length > 0) {
        checkTree(node.children, node.id, checkedIds, halfCheckedIds); // 递归检查子节点

        // 遍历子节点来确定父节点的状态
        node.children.forEach((child) => {
          if (child.checked) {
            someChildrenChecked = true;
            // 如果子节点被选中，可能需要将子节点的ID也加入checkedIds（取决于需求）
            // 但通常我们只关心父节点和叶子节点的checked状态
            halfCheckedIds.push(child.id); // 可选，根据需要添加
          } else {
            allChildrenChecked = false;
          }
        });

        // 根据子节点的状态更新父节点的状态及数组
        if (allChildrenChecked) {
          // 如果所有子节点都选中，则父节点也被视为选中
          checkedIds.push(node.id);
        } else if (someChildrenChecked) {
          // 如果部分子节点选中，则父节点被视为半选
          halfCheckedIds.push(parentId || node.id); // parentId用于处理递归时的父节点
        }
        // 注意：如果所有子节点都未选中，则父节点不会被添加到任何数组中
        // 但如果业务需求是即使所有子节点都未选中，父节点也需要以某种方式被标记，
        // 你需要在这里添加额外的逻辑。
      } else {
        // 如果是叶子节点，直接根据其checked状态处理
        if (node.checked) {
          checkedIds.push(node.id);
        }
      }
    });
    return { checkedIds, halfCheckedIds };
  }

  /**
   * 钩子函数
   */
  onMounted(() => {
    setFormData();
  });

  /**
   * 定义函数
   */
  defineExpose({
    openModal,
  });
</script>
<style lang="less"></style>
