<template>
	<a-drawer
		v-model:open="open"
		class="custom-class"
		:root-class-name="wrapClassName"
		:title="title"
		placement="right"
		:width="width"
		:mask-closable="false"
		:footer-style="{ textAlign: 'right' }"
		@after-open-change="afterOpenChange"
	>
		<form-render
			ref="formRender"
			v-model="bindValue"
			:config="config"
			:popup-container-id="wrapClassId"
			:items="formItems"
			:disabled-fields="disabledFields"
			:hidden-fields="hiddenFields"
			v-bind="$attrs"
		>
			<!-- 透传插槽 -->
			<template v-for="(item, key, index) in $slots" :key="index" #[key]>
				<template v-if="key != 'modal-footer'"><slot :name="key" :item="item" /></template>
			</template>
		</form-render>
		<template #footer>
			<a-button style="margin-right: 8px" @click="open = false">
				<template #icon>
					<icon-font type="icon-reset"></icon-font>
				</template>
				{{ $t('form.drawer.cancel') }}
			</a-button>
			<a-button type="primary" @click="handleOk">
				<template #icon>
					<icon-font type="icon-send"></icon-font>
				</template>
				{{ $t('form.drawer.submit') }}
			</a-button>
		</template>
	</a-drawer>
</template>

<script setup lang="ts">
	import XEUtils from 'xe-utils'
	import FormRender from './form-render.vue'
	import { FormValueType, FormConfig, FormItem } from './form-render-types'
	import { NamePath } from 'ant-design-vue/es/form/interface'

	const props = defineProps({
		wrapClassName: { type: String, default: '' },
		modalContentWrapperClassName: { type: String, default: '' },
		modelValue: {
			type: Object as PropType<Record<string, FormValueType>>,
			required: true,
		},
		title: {
			type: String,
			default: () => {
				return undefined
			},
		},
		// 表单项
		formItems: {
			type: Array as PropType<Array<FormItem>>,
			default: () => {
				return []
			},
		},
		config: {
			type: Object as PropType<FormConfig>,
			required: false,
			default: () => {
				return {
					layout: 'horizontal',
					colon: true,
					hideRequiredMark: false,
					labelAlign: 'right',
					labelType: 'fixed',
					scrollToFirstError: false,
					validateOnRuleChange: true,
					labelCol: { span: 4 },
				}
			},
		},
		disabledFields: {
			type: Array as PropType<Array<string>>,
			required: false,
			default: () => {
				return []
			},
		},
		// 要隐藏的表单项
		hiddenFields: {
			type: Array as PropType<Array<string>>,
			required: false,
			default: () => {
				return []
			},
		},
		// 最大高度
		maxHeight: {
			type: [String, Number],
			required: false,
			default: 'none',
		},
		// 弹框的宽
		width: {
			type: String,
			required: false,
			default: '750px',
		},
	})
	const { modelValue, title, width, wrapClassName, config, disabledFields, hiddenFields } = toRefs(props)
	const open = ref<boolean>(false)

	const afterOpenChange = (bool: boolean) => {
		if (bool) {
			formRender.value?.clearValidate()
		}
	}

	const emit = defineEmits<{
		'update:model-value': [value: Record<string, FormValueType>]
		ok: [value: Record<string, FormValueType>]
	}>()
	const wrapClassId = ref(XEUtils.uniqueId())
	const bindValue = computed({
		get: function () {
			return modelValue.value
		},
		set: function (value) {
			emit('update:model-value', value)
		},
	})
	const formRender = ref<typeof FormRender>()

	// 清空表单状态
	const reset = () => {
		bindValue.value = {}
		formRender.value?.clearValidate()
	}

	// 打开弹框
	const show = () => {
		open.value = true
	}

	// 关闭弹框，并清空表单状态
	const close = () => {
		reset()
		open.value = false
	}

	watch(
		open,
		(newVal) => {
			if (newVal) {
				nextTick(() => {
					formRender.value?.clearValidate()
				})
			}
		},
		{ immediate: true },
	)

	const handleOk = async () => {
		if (!formRender.value) {
			throw new Error('获取 formRender 失败')
		}
		try {
			await formRender.value.validateFields()
			emit('ok', bindValue.value)
		} catch (errorInfo) {
			console.error('errorInfo', errorInfo)
		}
	}

	// 校验表单
	const validateFields = async (nameList?: Array<NamePath>) => {
		if (!formRender.value) {
			throw new Error('获取 formRender 失败')
		}
		return await formRender.value.validateFields(nameList)
	}
	// 重置表单
	const resetFields = () => {
		formRender.value?.resetFields()
	}
	defineExpose({
		show,
		close,
		reset,
		validateFields,
		resetFields,
	})
</script>
