<template>
	<el-select ref="selectRef" v-model="defaultValue" :size="size" :clearable="clearable" :multiple="multiple"
			   :collapse-tags="collapseTags" :collapse-tags-tooltip="collapseTagsTooltip" :filterable="filterable"
			   :placeholder="placeholder" :disabled="disabled">
		<el-option v-for="(item, index) in tableData" :key="index" :label="item[defaultProps.label]"
				   :value="item[defaultProps.value]"></el-option>
	</el-select>
</template>

<script setup>
import config from '@/config/select'
import {ref, watch, onMounted} from 'vue'
import tools from "@/utils/tools"

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

const props = defineProps({
	modelValue: null,
	api: {type: Function, default: undefined},
	params: {type: Object, default: null},
	placeholder: {type: String, default: "请选择"},
	size: {type: String, default: "default"},
	clearable: {type: Boolean, default: false},
	multiple: {type: Boolean, default: false},
	filterable: {type: Boolean, default: false},
	collapseTags: {type: Boolean, default: false},
	collapseTagsTooltip: {type: Boolean, default: false},
	disabled: {type: Boolean, default: false},
	props: {
		type: Object, default: () => {
		}
	},
	cacheKey: {type: String, default: ""}
})

const selectRef = ref(null)
let loading = ref(false)
let defaultValue = ref([])
let defaultProps = ref({
	label: config.props.label,
	value: config.props.value
})
let tableData = ref([])

watch(() => props.modelValue, (val) => {
	defaultValue.value = val
}, {deep: true, immediate: true})

watch(defaultValue, () => {
	emit('update:modelValue', defaultValue.value)
	emit('change', defaultValue.value)
})

onMounted(() => {
	getData()
	defaultProps.value = Object.assign(defaultProps.value, props.props);
	defaultValue.value = props.modelValue
})

async function getData() {
	if (!props.api) return;
	loading.value = true;
	const cacheKey = genCacheKey()
	if (cacheKey) {
		const data = tools.data.get(cacheKey)
		if (data) {
			tableData.value = data;
			loading.value = false;
			return;
		}
	}
	const res = await props.api(props.params);
	tableData.value = res.data;
	if (cacheKey) {
		tools.data.set(cacheKey, res.data, 7200)
	}
	loading.value = false;
}

function genCacheKey() {
	if (!props.cacheKey) {
		return null;
	}
	return `${props.cacheKey || props.api.name}:` + tools.md5(`${stableStringify(props.params)}`).slice(0, 8).toUpperCase()
}

function stableStringify(obj) {
	if (obj === null || typeof obj !== 'object') return String(obj)
	if (Array.isArray(obj)) {
		return `[${obj.map(stableStringify).join(',')}]`
	}
	return `{${Object.keys(obj)
		.sort()
		.map(k => `"${k}":${stableStringify(obj[k])}`)
		.join(',')}}`
}
</script>

<style scoped>

</style>
