<template>
	<a-form :model="formData" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol" :layout="layout" @finish="handleFinish" @finish-failed="handleFinishFailed">
		<a-form-item v-for="item in formItems" :key="item.field" :label="item.label" :name="item.field" :required="item.required" :colon="item.colon">
			<!-- 输入框 -->
			<template v-if="item.type === 'input'">
				<a-input
					v-model:value="formData[item.field]"
					:placeholder="item.placeholder || `请输入${item.label}`"
					:disabled="item.disabled"
					:allow-clear="item.allowClear !== false"
					:max-length="item.maxLength"
					:type="item.inputType || 'text'"
					:prefix="item.prefix"
					:suffix="item.suffix"
					@change="item.onChange && item.onChange(formData[item.field])"
				/>
			</template>

			<!-- 文本域 -->
			<template v-else-if="item.type === 'textarea'">
				<a-textarea
					v-model:value="formData[item.field]"
					:placeholder="item.placeholder || `请输入${item.label}`"
					:disabled="item.disabled"
					:allow-clear="item.allowClear !== false"
					:rows="item.rows || 4"
					:max-length="item.maxLength"
					:show-count="item.showCount"
					@change="item.onChange && item.onChange(formData[item.field])"
				/>
			</template>

			<!-- 密码输入框 -->
			<template v-else-if="item.type === 'password'">
				<a-input-password v-model:value="formData[item.field]" :placeholder="item.placeholder || `请输入${item.label}`" :disabled="item.disabled" :max-length="item.maxLength" @change="item.onChange && item.onChange(formData[item.field])" />
			</template>

			<!-- 数字输入框 -->
			<template v-else-if="item.type === 'number'">
				<a-input-number
					v-model:value="formData[item.field]"
					:placeholder="item.placeholder || `请输入${item.label}`"
					:disabled="item.disabled"
					:min="item.min"
					:max="item.max"
					:step="item.step || 1"
					:precision="item.precision"
					:controls="item.controls !== false"
					style="width: 100%"
					@change="item.onChange && item.onChange(formData[item.field])"
				/>
			</template>

			<!-- 下拉选择 -->
			<template v-else-if="item.type === 'select'">
				<a-select
					v-model:value="formData[item.field]"
					:placeholder="item.placeholder || `请选择${item.label}`"
					:disabled="item.disabled"
					:allow-clear="item.allowClear !== false"
					:mode="item.mode"
					:options="item.options"
					:field-names="item.fieldNames"
					style="width: 100%"
					@change="item.onChange && item.onChange(formData[item.field])"
				>
					<template v-if="!item.options" #notFoundContent>
						<a-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" description="暂无数据" />
					</template>
				</a-select>
			</template>

			<!-- 单选框 -->
			<template v-else-if="item.type === 'radio'">
				<a-radio-group v-model:value="formData[item.field]" :disabled="item.disabled" :button-style="item.buttonStyle" @change="item.onChange && item.onChange(formData[item.field])">
					<template v-if="item.options">
						<a-radio v-for="opt in item.options" :key="opt.value" :value="opt.value" :disabled="opt.disabled">
							{{ opt.label }}
						</a-radio>
					</template>
					<template v-else-if="item.buttonStyle === 'solid'">
						<a-radio-button v-for="opt in item.options" :key="opt.value" :value="opt.value" :disabled="opt.disabled">
							{{ opt.label }}
						</a-radio-button>
					</template>
				</a-radio-group>
			</template>

			<!-- 多选框 -->
			<template v-else-if="item.type === 'checkbox'">
				<a-checkbox-group v-model:value="formData[item.field]" :disabled="item.disabled" @change="item.onChange && item.onChange(formData[item.field])">
					<template v-if="item.options">
						<a-checkbox v-for="opt in item.options" :key="opt.value" :value="opt.value" :disabled="opt.disabled">
							{{ opt.label }}
						</a-checkbox>
					</template>
				</a-checkbox-group>
			</template>

			<!-- 开关 -->
			<template v-else-if="item.type === 'switch'">
				<a-switch v-model:checked="formData[item.field]" :disabled="item.disabled" :checked-children="item.checkedChildren || '开'" :un-checked-children="item.unCheckedChildren || '关'" @change="item.onChange && item.onChange(formData[item.field])" />
			</template>

			<!-- 日期选择 -->
			<template v-else-if="item.type === 'date'">
				<a-date-picker
					v-model:value="formData[item.field]"
					:placeholder="item.placeholder || `请选择${item.label}`"
					:disabled="item.disabled"
					:format="item.format || 'YYYY-MM-DD'"
					:value-format="item.valueFormat || 'YYYY-MM-DD'"
					style="width: 100%"
					@change="item.onChange && item.onChange(formData[item.field])"
				/>
			</template>

			<!-- 日期范围选择 -->
			<template v-else-if="item.type === 'dateRange'">
				<a-range-picker
					v-model:value="formData[item.field]"
					:placeholder="item.placeholder || ['开始日期', '结束日期']"
					:disabled="item.disabled"
					:format="item.format || 'YYYY-MM-DD'"
					:value-format="item.valueFormat || 'YYYY-MM-DD'"
					style="width: 100%"
					@change="item.onChange && item.onChange(formData[item.field])"
				/>
			</template>

			<!-- 时间选择 -->
			<template v-else-if="item.type === 'time'">
				<a-time-picker
					v-model:value="formData[item.field]"
					:placeholder="item.placeholder || `请选择${item.label}`"
					:disabled="item.disabled"
					:format="item.format || 'HH:mm:ss'"
					:value-format="item.valueFormat || 'HH:mm:ss'"
					style="width: 100%"
					@change="item.onChange && item.onChange(formData[item.field])"
				/>
			</template>

			<!-- 上传 -->
			<template v-else-if="item.type === 'upload'">
				<a-upload
					v-model:file-list="formData[item.field]"
					:list-type="item.listType || 'text'"
					:action="item.action"
					:max-count="item.maxCount"
					:before-upload="item.beforeUpload"
					:custom-request="item.customRequest"
					:accept="item.accept"
					:disabled="item.disabled"
					@change="(info) => item.onChange && item.onChange(info)"
				>
					<a-button v-if="item.listType !== 'picture-card'" type="primary">
						<UploadOutlined />
						点击上传
					</a-button>
					<div v-else>
						<PlusOutlined />
						<div class="ant-upload-text">上传</div>
					</div>
				</a-upload>
			</template>

			<!-- 评分 -->
			<template v-else-if="item.type === 'rate'">
				<a-rate v-model:value="formData[item.field]" :disabled="item.disabled" :count="item.count || 5" :allow-half="item.allowHalf" @change="item.onChange && item.onChange(formData[item.field])" />
			</template>

			<!-- 滑块 -->
			<template v-else-if="item.type === 'slider'">
				<a-slider v-model:value="formData[item.field]" :disabled="item.disabled" :min="item.min || 0" :max="item.max || 100" :step="item.step || 1" :marks="item.marks" :range="item.range" @change="item.onChange && item.onChange(formData[item.field])" />
			</template>

			<!-- 级联选择 -->
			<template v-else-if="item.type === 'cascader'">
				<a-cascader
					v-model:value="formData[item.field]"
					:options="item.options"
					:placeholder="item.placeholder || `请选择${item.label}`"
					:disabled="item.disabled"
					:change-on-select="item.changeOnSelect"
					:field-names="item.fieldNames"
					style="width: 100%"
					@change="item.onChange && item.onChange(formData[item.field])"
				/>
			</template>

			<!-- 自定义插槽 -->
			<template v-else-if="item.type === 'slot'">
				<slot :name="item.slotName || item.field" :field="item.field" :value="formData[item.field]"></slot>
			</template>

			<!-- 提示信息 -->
			<template v-if="item.tip">
				<div class="form-item-tip">{{ item.tip }}</div>
			</template>
		</a-form-item>

		<!-- 表单操作按钮 -->
		<a-form-item v-if="showActions" :wrapper-col="actionWrapperCol">
			<a-space>
				<a-button type="primary" html-type="submit" :loading="loading" :size="buttonSize">
					{{ submitText || '提交' }}
				</a-button>
				<a-button v-if="showReset" @click="handleReset" :size="buttonSize">
					{{ resetText || '重置' }}
				</a-button>
				<a-button v-if="showCancel" @click="handleCancel" :size="buttonSize">
					{{ cancelText || '取消' }}
				</a-button>
				<slot name="actions"></slot>
			</a-space>
		</a-form-item>

		<!-- 自定义插槽 -->
		<slot></slot>
	</a-form>
</template>

<script setup>
import { ref, reactive, computed, watch } from 'vue'
import { Empty } from 'ant-design-vue'
import { UploadOutlined, PlusOutlined } from '@ant-design/icons-vue'

const props = defineProps({
	// 表单项配置
	formItems: {
		type: Array,
		default: () => [],
		required: true,
	},
	// 表单初始值
	initialValues: {
		type: Object,
		default: () => ({}),
	},
	// 表单布局
	layout: {
		type: String,
		default: 'horizontal', // horizontal, vertical, inline
	},
	// 标签宽度
	labelCol: {
		type: Object,
		default: () => ({ span: 6 }),
	},
	// 内容宽度
	wrapperCol: {
		type: Object,
		default: () => ({ span: 16 }),
	},
	// 是否显示操作按钮
	showActions: {
		type: Boolean,
		default: true,
	},
	// 操作按钮布局
	actionWrapperCol: {
		type: Object,
		default: () => ({ offset: 6, span: 16 }),
	},
	// 是否显示重置按钮
	showReset: {
		type: Boolean,
		default: true,
	},
	// 是否显示取消按钮
	showCancel: {
		type: Boolean,
		default: false,
	},
	// 按钮文字
	submitText: String,
	resetText: String,
	cancelText: String,
	// 按钮大小
	buttonSize: {
		type: String,
		default: 'middle',
	},
	// 加载状态
	loading: {
		type: Boolean,
		default: false,
	},
})

const emit = defineEmits(['finish', 'finish-failed', 'reset', 'cancel'])

// 表单数据
const formData = reactive({ ...props.initialValues })

// 表单验证规则
const rules = computed(() => {
	const result = {}
	props.formItems.forEach((item) => {
		if (item.rules && item.rules.length > 0) {
			result[item.field] = item.rules
		}
	})
	return result
})

// 监听初始值变化
watch(
	() => props.initialValues,
	(newVal) => {
		Object.assign(formData, newVal)
	},
	{ deep: true },
)

// 表单提交
const handleFinish = (values) => {
	emit('finish', values)
}

// 表单验证失败
const handleFinishFailed = (errorInfo) => {
	emit('finish-failed', errorInfo)
}

// 重置表单
const handleReset = () => {
	Object.assign(formData, props.initialValues)
	emit('reset', formData)
}

// 取消操作
const handleCancel = () => {
	emit('cancel')
}

// 暴露方法给父组件
defineExpose({
	formData,
	resetForm: handleReset,
	setFieldValue: (field, value) => {
		formData[field] = value
	},
	getFieldValue: (field) => {
		return formData[field]
	},
	setFieldsValue: (values) => {
		Object.assign(formData, values)
	},
})
</script>

<style scoped lang="scss">
.form-item-tip {
	margin-top: 4px;
	font-size: 12px;
	color: #999;
	line-height: 1.5;
}
</style>
