<template>
	<el-tree
		ref="treeRef"
		:data="menuData"
		:props="defaultTreeProps"
		:default-checked-keys="menuDefaultCheckedKeys"
		@check-change="handleMenuChange"
		@node-click="handleMenuClick"
		node-key="id"
		check-strictly
		highlight-current
		show-checkbox
		default-expand-all
	>
	</el-tree>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { RoleDrawerStores } from '../stores/RoleDrawerStores';
import { RoleMenuTreeStores } from '../stores/RoleMenuTreeStores';
import { RoleMenuBtnStores } from '../stores/RoleMenuBtnStores';
import { RoleMenuFieldStores } from '../stores/RoleMenuFieldStores';
import { RoleMenuFieldHeaderStores } from '../stores/RoleMenuFieldStores';
import { getRoleMenu, getRoleMenuBtnField, setRoleMenu } from './api';
import { ElMessage } from 'element-plus';
import XEUtils from 'xe-utils';
import { RoleMenuTreeType } from '../types';

const RoleDrawer = RoleDrawerStores(); // 角色-抽屉
const RoleMenuTree = RoleMenuTreeStores(); // 角色-菜单
const RoleMenuBtn = RoleMenuBtnStores(); // 角色-菜单-按钮
const RoleMenuField = RoleMenuFieldStores(); // 角色-菜单-列字段
const RoleMenuFieldHeader = RoleMenuFieldHeaderStores();// 角色-菜单-列字段
const treeRef = ref();
const menuData = ref<RoleMenuTreeType[]>([]); // 菜单列表数据
const menuDefaultCheckedKeys = ref<(number | string | undefined)[]>([]); // 默认选中的菜单列表
// 菜单配置
const defaultTreeProps = {
	children: 'children',
	label: 'name',
	value: 'id',
};

// 避免编程式勾选触发重复事件
let isSyncingChildren = false;

// 收集指定节点下所有子级的 id（不包含自身）
const collectDescendantIds = (nodes: any[]): (number | string | undefined)[] => {
	const result: (number | string | undefined)[] = [];
	const stack = [...nodes];
	while (stack.length) {
		const current: any = stack.pop();
		if (!current) continue;
		if (current.id !== undefined && current.id !== null) {
			result.push(current.id);
		}
		if (Array.isArray(current.children) && current.children.length) {
			for (const child of current.children) stack.push(child);
		}
	}
	return result;
};

/**
 * 菜单复选框选中
 * @param node：当前节点的 Node 对象
 * @param checked：布尔值，表示当前节点是否被选中
 */
const handleMenuChange = async (data: any, checked: boolean) => {
	if (isSyncingChildren) return;
	// 先处理当前节点
	await setRoleMenu({ roleId: RoleDrawer.roleId, menuId: data.id, isCheck: checked }).then((res: any) => {
		ElMessage({ message: res.msg, type: 'success' });
	});
	// 仅当一级节点被切换时，联动其所有子级
	const node = treeRef?.value?.getNode?.(data);
	if (node && node.level === 1 && Array.isArray(data.children) && data.children.length) {
		const ids = collectDescendantIds(data.children);
		if (ids.length) {
			isSyncingChildren = true;
			try {
				// 本地勾选/取消勾选所有子级，不影响其他节点
				for (const id of ids) {
					if (id !== undefined && id !== null) {
						treeRef.value.setChecked(id, checked, false);
					}
				}
				// 同步服务端权限
				await Promise.all(
					ids.filter((id) => id !== undefined && id !== null)
						.map((id) => setRoleMenu({ roleId: RoleDrawer.roleId, menuId: id, isCheck: checked }))
				);
			} finally {
				isSyncingChildren = false;
			}
		}
	}
	// 当子节点被勾选时，向上勾选所有父级（不联动取消），避免影响其他分支
	if (checked && node) {
		const parents: any[] = [];
		let p = node.parent;
		while (p && p.data) {
			parents.push(p.data);
			p = p.parent;
		}
		// 仅保留有有效 id 的父级
		const validParents = parents.filter((p) => p && p.id !== undefined && p.id !== null);
		if (validParents.length) {
			isSyncingChildren = true;
			try {
				for (const parentData of validParents) {
					treeRef.value.setChecked(parentData.id, true, false);
				}
				await Promise.all(
					validParents.map((parentData) => setRoleMenu({ roleId: RoleDrawer.roleId, menuId: parentData.id, isCheck: true }))
				);
			} finally {
				isSyncingChildren = false;
			}
		}
	}
};
/**
 * 菜单点击事件
 */
const handleMenuClick = async (selectNode: RoleMenuTreeType) => {
	if (!selectNode.is_catalog) {
		RoleMenuTree.setRoleMenuTree(selectNode); // 更新当前选中的菜单
		// 获取当前菜单的按钮列表
		const { data } = await getRoleMenuBtnField({
			roleId: RoleDrawer.roleId,
			menuId: selectNode.id,
		});
		RoleMenuBtn.setState(data.menu_btn); // 更新按钮列表
		RoleMenuField.setState(data.menu_field); // 更新列字段列表
	} else {
		RoleMenuBtn.setState([]); // 更新按钮列表
		RoleMenuField.setState([]); // 更新列字段列表
	}
	RoleMenuFieldHeader.$reset()
};

// 递归过滤树形数据，过滤掉指定 id 的节点
const filterTreeData = (data: RoleMenuTreeType[], excludeId: number | string): RoleMenuTreeType[] => {
	return data
		.filter((item) => item.id !== excludeId)
		.map((item) => {
			if (Array.isArray(item?.children) && item?.children?.length > 0) {
				return {
					...item,
					children: filterTreeData(item?.children, excludeId),
				};
			}
			return item;
		});
};

// 页面打开后获取列表数据
onMounted(async () => {
	menuData.value = await getRoleMenu({ roleId: RoleDrawer.roleId });
	menuData.value = menuData.value.filter((item: any) => !item.name.includes('商户列表') && !item.name.includes('商户账号'));
	// 过滤掉 id 为 9 的常规配置
	/* menuData.value = filterTreeData(menuData.value, 9); */
	menuDefaultCheckedKeys.value = XEUtils.toTreeArray(menuData.value)
		.filter((i) => i.isCheck)
		.map((i) => i.id);
});
</script>
