import { useCrud, useForm } from '@cool-vue/crud';
import { cloneDeep, isEmpty, isFunction, isString } from 'lodash-es';
import {
	computed,
	defineComponent,
	onActivated,
	onMounted,
	type PropType,
	ref,
	type Ref,
	toValue,
	useModel
} from 'vue';
import { deepTree, parsePx } from '/@/cool/utils';
import { useI18n } from 'vue-i18n';
import { useCool } from '/@/cool';
import { CrudProps } from '../../comm';

export default defineComponent({
	name: 'cl-select',

	props: {
		...CrudProps,
		modelValue: [String, Number, Array],
		options: {
			type: [Array, Object] as PropType<any[] | Ref<any[]>>,
			default: () => []
		},
		prop: String,
		labelKey: {
			type: String,
			default: 'label'
		},
		valueKey: {
			type: String,
			default: 'value'
		},
		width: [String, Number],

		// 是否树形
		tree: Boolean,
		// 是否返回选中层级下的所有值
		allLevelsId: Boolean,
		// 是否父子不互相关联
		checkStrictly: Boolean,
		// 默认展开所有
		defaultExpandAll: Boolean,
		// 顶级标签
		topLabel: String,
		// 是否选择当前表格数据，如果是，则不能选择自身及其下级
		current: Boolean,

		// 请求接口，如果是字符串，则使用 crud 下的方法
		api: [String, Function],

		// 值变化刷新
		refreshOnChange: {
			type: Boolean,
			default: true
		},
		// 是否在激活时刷新
		refreshOnActivated: {
			type: Boolean,
			default: true
		}
	},

	emits: ['update:modelValue', 'change'],

	setup(props, { emit, expose }) {
		const { refs, setRefs, route } = useCool();
		const { t } = useI18n();

		// cl-crud
		const Crud = useCrud();

		// cl-form
		const Form = useForm();

		// 是否用于搜索
		const isSearch = computed(() => !Form.value || Form.value?.name === 'search');

		// 选项
		const options = ref<Dict.Item[]>();

		// 选中值
		const value = useModel(props, 'modelValue');

		// 列表
		const list = computed(() => {
			let data: any[] = [];

			if (props.current) {
				data = cloneDeep(toValue(Crud.value?.['cl-table']?.data));

				// 禁用自身及其下级
				function deep(d: any, f: boolean) {
					if (d.id && d.id == Form.value?.getForm('id')) {
						f = true;
					}

					if (f) {
						d.disabled = true;
					}

					if (d.children) {
						d.children.forEach((e: any) => {
							deep(e, f);
						});
					}
				}

				deep({ children: data }, false);
			} else {
				data = toValue(options.value || props.options) || [];
			}

			// 如果存在顶级标签
			if (props.topLabel) {
				return [
					{
						[props.labelKey]: props.topLabel,
						[props.valueKey]: 0,
						children: data
					}
				];
			}

			return data;
		});

		// 获取值
		function getValue(val: any): any | any[] {
			if (props.allLevelsId) {
				const ids: any[] = [];

				// 获取所有的值
				const deep = (arr: Dict.Item[], f: boolean) => {
					arr.forEach(e => {
						const f2 = e[props.valueKey] == val;

						if (f || f2) {
							ids.push(e[props.valueKey]);
						}

						if (e.children) {
							deep(e.children, f || f2);
						}
					});
				};

				deep(list.value, false);

				return isEmpty(ids) ? undefined : ids;
			} else {
				return val === '' ? undefined : val;
			}
		}

		// 值改变
		function onChange(val: any) {
			const v = getValue(val);

			emit('update:modelValue', v);
			emit('change', v);

			if (isSearch.value) {
				if (props.prop && props.refreshOnChange) {
					Crud.value?.refresh({ page: 1, [props.prop]: v });
				}
			}
		}

		// 聚焦
		function focus() {
			refs.select?.focus();
		}

		// 获取选项数据
		function refresh() {
			let req: Promise<any> | null = null;

			if (isString(props.api)) {
				req = Crud.value?.service[props.api]();
			}

			if (isFunction(props.api)) {
				req = props.api();
			}

			if (req) {
				req.then(res => {
					options.value = deepTree(res);
				});
			}
		}

		onMounted(() => {
			if (props.api) {
				refresh();

				onActivated(() => {
					if (props.refreshOnActivated) {
						if (!Form.value || Form.value?.name == 'search') {
							refresh();
						}
					}
				});
			}
		});

		expose({
			focus
		});

		return () => {
			// 样式
			const style = {
				width: parsePx(props.width!)
			};

			// 占位符
			const placeholder = isSearch.value ? t('全部') : t('请选择');

			// 树形下拉框
			const TreeSelect = (
				<el-tree-select
					v-model={value.value}
					clearable
					filterable
					placeholder={placeholder}
					disabled={props.disabled}
					data={list.value}
					checkStrictly={props.allLevelsId || props.checkStrictly}
					defaultExpandAll={props.defaultExpandAll}
					props={{
						label: props.labelKey,
						value: props.valueKey
					}}
					style={style}
					onChange={onChange}
					ref={setRefs('select')}
				/>
			);

			// 普通下拉框
			const Select = (
				<el-select
					v-model={value.value}
					clearable
					filterable
					disabled={props.disabled}
					placeholder={placeholder}
					style={style}
					onChange={onChange}
					ref={setRefs('select')}
				>
					{list.value?.map(e => {
						return isString(e) ? (
							<el-option label={e} value={e} />
						) : (
							<el-option
								disabled={e.disabled}
								label={e[props.labelKey]}
								value={e[props.valueKey]}
							/>
						);
					})}
				</el-select>
			);

			return props.tree ? TreeSelect : Select;
		};
	}
});
