<template>
	<el-select
		v-model="state.id"
		:disabled="props.disabled"
		:placeholder="props.placeholder"
		ref="selectRef"
		:clearable="props.clearable"
		@clear="clear"
		:filterable="props.filterable"
		:filter-method="filterMethod"
	>
		<template #default>
			<el-option hidden key="id" :value="state.id" :label="state.name"> </el-option>
			<el-tree
				node-key="id"
				:load="loadNode"
				lazy
				v-if="lazyShow"
				:props="treeProps"
				:filter-node-method="filterNode"
				@node-click="nodeClick"
				:default-expanded-keys="state.externalArr"
				v-loading="loading"
				highlight-current
				check-strictly
				ref="treeRef"
				:show-checkbox="props.showCheckbox"
				@check="checkChange"
				check-on-click-node
				:expand-on-click-node="expandOnClickNode"
			/>
			<el-tree
				ref="treeRef"
				:data="state.treeData"
				node-key="id"
				v-else
				default-expand-all
				highlight-current
				:props="treeProps"
				v-loading="loading"
				:filter-node-method="filterNode"
				@node-click="nodeClick"
				check-strictly
				:show-checkbox="props.showCheckbox"
				@check="checkChange"
				check-on-click-node
			/>
		</template>
		<template #footer v-if="props.showCheckbox">
			<div class="flex-end">
				<el-button type="primary" @click="chooseHotSpot" size="small">确定</el-button>
				<el-button @click="reset" size="small">重置</el-button>
			</div>
		</template>
	</el-select>
</template>
<script setup lang="ts">
import { computed, reactive, ref, watch } from 'vue';
import { hotSpotSearch, hotSpotType } from '@/api/business/order';
import { removeDuplicate } from '@/utils/arrayOperation';
import { treeEventClass, treeEventClassSearch } from '@/api/auxiliary/eventClass';

const props = defineProps({
	modelValue: {
		type: [String, Array],
		default: () => '',
	},
	type: {
		type: String,
		default: 'hotspot',
	},
	disabled: {
		type: Boolean,
		default: false,
	},
	placeholder: {
		type: String,
		default: '请选择',
	},
	externalArr: {
		// 外部传入的父级id数组 懒加载时使用
		type: Array,
		default: () => [],
	},
	showCheckbox: {
		// 是否显示多选
		type: Boolean,
		default: false,
	},
	clearable: {
		type: Boolean,
		default: false,
	},
	checkStrictly: {
		// 任意一级
		type: Boolean,
		default: false,
	},
	filterable: {
		type: Boolean,
		default: true,
	},
} as any);
const inputPlaceholder = computed(() => {
	return props.type === 'hotspot' ? '热点名称' : '事件名称';
});
// 选择节点展开
const expandOnClickNode = computed(() => {
	return !props.checkStrictly;
});
const treeProps = computed(() => {
	return {
		label: props.type === 'hotspot' ? 'hotSpotFullName' : 'eventFullName',
		children: 'children',
		isLeaf: 'hasChild',
	};
});

const emit = defineEmits(['choose', 'update:modelValue']);

const state = reactive<any>({
	id: '',
	name: '',
	treeData: [],
	externalArr: [],
	external: [],
	checkedKeys: [],
	checkNodes: [],
});

watch(
	() => props.externalArr,
	(val) => {
		if (val) {
			state.externalArr = val;
		}
	},
	{ immediate: true }
);

const lazyShow = ref(true);
const loading = ref(false);
// 懒加载
const treeRef = ref<RefType>();
const loadNode = async (node: any, resolve: any) => {
	if (node.isLeaf) return resolve([]);
	const { showCheckbox, type, modelValue } = props;
	try {
		loading.value = true;
		const method = type === 'hotspot' ? hotSpotType : treeEventClass;
		const { result } = await method({ id: node.data.id ? node.data.id : null });
		resolve(result);
		state.id = modelValue;
		if (showCheckbox) {
			treeRef.value.setCheckedKeys(modelValue);
			const nodes = treeRef.value.getCheckedNodes();
			if (type === 'hotspot') state.name = nodes.map((item: any) => item.hotSpotFullName).join(',') ?? '';
			else state.name = nodes.map((item: any) => item.eventFullName).join(',') ?? '';
		} else {
			treeRef.value.setCurrentKey(modelValue);
			const currentNode = treeRef.value.getNode(modelValue);
			if (type === 'hotspot') state.name = currentNode.data.hotSpotFullName;
			else state.name = currentNode.data.eventFullName;
		}
		loading.value = false;
	} catch (e) {
		loading.value = false;
	}
};
// 搜索
const filterMethod = (value: string) => {
	if (value) {
		lazyShow.value = false; //当输入框有值时关闭懒加载
		loading.value = true;
		const { type } = props;
		const method = type === 'hotspot' ? hotSpotSearch : treeEventClassSearch;
		method(value)
			.then((res) => {
				//获取后端搜索的数据 	//selectMacTree是我自己的后端接口，你们换成自己的
				state.treeData.length = 0;
				state.treeData = res.result ?? [];
				treeRef.value!.filter(value);
				if (props.showCheckbox && state.checkedKeys.length) {
					treeRef.value.setCheckedKeys(state.checkedKeys);
				}
				if (props.modelValue) {
					setTimeout(() => {
						treeRef.value.setCurrentKey(props.modelValue);
					}, 100);
				}
				loading.value = false;
			})
			.catch((e) => {
				loading.value = false;
			});
	} else if (value == '' || value == ' ' || value == null) {
		lazyShow.value = true; // 懒加载树显示
	}
};
// 查询
const filterNode = (value: string, data: any) => {
	if (!value) return true;
	return data.hotSpotFullName.includes(value);
};
// 单选
const selectRef = ref<RefType>();
const nodeClick = async (val: any, node: any) => {
	const { showCheckbox, checkStrictly, type } = props;
	if (showCheckbox) return;
	if (checkStrictly) {
		state.externalArr = [];
		state.external = [];
		state.externalArr = getParentId(node, state.external);
		if (type === 'hotspot') state.name = val.hotSpotFullName;
		else state.name = val.eventFullName;
		state.id = val.id;
		emit('update:modelValue', val.id);
		emit('choose', { externalArr: state.externalArr, ...val });
		selectRef.value.blur();
	}
	if (!node?.isLeaf) return;
	state.externalArr = [];
	state.external = [];
	state.externalArr = getParentId(node, state.external);
	if (type === 'hotspot') state.name = val.hotSpotFullName;
	else state.name = val.eventFullName;
	state.id = val.id;
	emit('update:modelValue', val.id);
	emit('choose', { externalArr: state.externalArr, ...val });
	selectRef.value.blur();
};
// 多选
const checkChange = (val: any, e: any) => {
	const { showCheckbox, type } = props;
	if (!showCheckbox) return;
	const current = treeRef.value.getNode(val);
	state.checkedKeys = e.checkedKeys;
	state.checkedNodes = e.checkedNodes;
	state.id = e.checkedKeys;
	if (type === 'hotspot') state.name = e.checkedNodes.map((item: any) => item.hotSpotFullName).join(',') ?? '';
	else state.name = e.checkedNodes.map((item: any) => item.eventFullName).join(',') ?? '';
	if (props.externalArr.length) {
		state.externalArr = props.externalArr.concat(getParentId(current, state.external));
	} else {
		state.externalArr = getParentId(current, state.external);
	}
	emit('choose', state.checkedKeys, state.checkedNodes, state.externalArr);
	emit('update:modelValue', e.checkedKeys);
};
// 多选确定
const chooseHotSpot = () => {
	emit('update:modelValue', state.checkedKeys);
	emit('choose', state.checkedKeys, state.checkedNodes, state.externalArr);
	selectRef.value.blur();
};
// 重置
const reset = () => {
	state.checkedKeys = [];
	treeRef.value.setCheckedKeys([]);
	state.name = '';
	emit('choose', [], [], []);
	emit('update:modelValue', []);
};
// 递归查找父级Id
const getParentId = (val: any, arr: string[]) => {
	if (val.data.parentId) {
		arr.push(val.data.parentId);
		getParentId(val.parent, arr);
	}
	return removeDuplicate(arr);
};
// 清空
const clear = () => {
	if (props.showCheckbox) {
		state.checkedKeys = [];
		treeRef.value.setCheckedKeys([]);
		state.name = '';
		state.id = [];
		emit('choose', [], [], []);
		emit('update:modelValue', []);
	} else {
		state.id = '';
		state.name = '';
		treeRef.value.setCurrentKey(null);
		emit('choose', {});
		emit('update:modelValue', '');
	}
};
defineExpose({
	reset,
	clear,
});
</script>
