<script setup lang="ts">
import type { WritableComputedRef } from "vue"
import type { FormItemRule } from "element-plus/es/components/form/src/types"
import type { VbFormItem } from "@@@/form/models"
import getConfigRule, { RULE_KEYS } from "@@/config/rules"

const props = withDefaults(
	defineProps<{
		data: any
		item: VbFormItem
		labelWidth?: number | string
		rules?: Record<string, FormItemRule[]>
		gutter?: number
		span?: number
		size?: "large" | "default" | "small"
	}>(),
	{
		gutter: 20,
		span: 24,
		size: "large"
	}
)
const emits = defineEmits<(e: "update:data", v: any) => void>()
const { item } = toRefs(props)
const itemId = computed(() => {
	return typeof item.value.id == "function" ? item.value.id() : item.value.id
})
const itemData = computed(() => {
	return typeof item.value.data == "function" ? item.value.data() : item.value.data
})
const isShow = computed(() => {
	if (props.item.show == undefined) {
		return true
	}
	if (typeof props.item.show == "function") {
		return props.item.show(data.value)
	}
	return props.item.show
})
const isNum = computed(() => {
	if (item.value.type == "number") {
		return true
	}
	if (item.value.rules && item.value.rules.length > 0) {
		return (
			item.value.rules.includes(RULE_KEYS.NUMBER) ||
			item.value.rules.includes(RULE_KEYS.REQUIRED_NUMBER) ||
			item.value.rules.includes(RULE_KEYS.N_MAX) ||
			item.value.rules.includes(RULE_KEYS.N_MIN) ||
			item.value.rules.includes(RULE_KEYS.N_MIN_MAX)
		)
	}
	return false
})
const data: WritableComputedRef<any> = computed({
	get(): any {
		return props.data
	},
	set(value: any): void {
		emits("update:data", value)
	}
})

const getRules = (item: VbFormItem): FormItemRule[] => {
	const _rules = [] as FormItemRule[]
	if (item.rules) {
		for (let i = 0; i < item.rules.length; i++) {
			const r = item.rules[i]
			let rule
			if (typeof r == "string") {
				rule = props.rules
					? props.rules[r]
					: getConfigRule(r, item.ruleFormat ? item.ruleFormat[i] : undefined)
				if (rule) {
					Array.isArray(rule) ? _rules.push(...rule) : _rules.push(rule)
				}
			} else if (typeof r == "object") {
				Array.isArray(r) ? _rules.push(...r) : _rules.push(r)
			}
		}
	}

	// 添加默认的 required 规则
	if (
		item.required &&
		_rules.find((v) => {
			return v.required == true
		}) == null
	) {
		const rule = getConfigRule(RULE_KEYS.REQUIRED, [item.label?.toString() ?? ""])
		if (rule) {
			Array.isArray(rule) ? _rules.push(...rule) : _rules.push(rule)
		}
	}
	// console.log("RULES===", _rules)
	return _rules
}
function checkComponent(name: string) {
	// if (!props.item?.component && name == "I") {
	//   return true
	// }
	const component = props.item?.component ?? "I"
	return typeof component == "string"
		? component.toLocaleUpperCase() == name.toLocaleUpperCase()
		: (component as any).name == name
}
function isDisable(item: any) {
	if (typeof item.disabled == "function") {
		return item.disabled(item)
	}
	return item.disabled
}

function init() {
	//
}

onMounted(() => {
	init()
})
</script>
<template>
	<el-col v-if="isShow" :span="item.span || span">
		<el-form-item
			:prop="item.field"
			:class="item.itemClass"
			:style="item.itemStyle"
			:required="item.required"
			:rules="getRules(item)"
			:label="item.label"
			:label-width="
				Number(item.labelWidth || labelWidth)
					? (item.labelWidth || labelWidth) + 'px'
					: item.labelWidth || labelWidth
			"
			v-bind="item.itemProps">
			<slot v-if="checkComponent('slot')" :name="item.field"></slot>
			<div
				v-else-if="checkComponent('text') || checkComponent('innerText')"
				:id="itemId"
				:class="item.class"
				:style="item.style">
				{{ item.innerText || data[item.field] }}
			</div>
			<template v-else-if="checkComponent('I') || checkComponent('ElInput')">
				<el-input
					v-if="isNum"
					v-model.number="data[item.field]"
					:id="itemId"
					:required="item.required"
					:type="item.type || 'text'"
					:class="item.class"
					:style="item.style"
					:placeholder="item.placeholder ?? item.label"
					:size="item.size"
					v-bind="item.props"
					v-on="item.listeners"></el-input>
				<el-input
					v-else
					v-model="data[item.field]"
					:id="itemId"
					:required="item.required"
					:type="item.type || 'text'"
					:class="item.class"
					:style="item.style"
					:placeholder="item.placeholder ?? item.label"
					:size="item.size"
					v-bind="item.props"
					v-on="item.listeners"></el-input>
			</template>
			<template v-else-if="checkComponent('VS') || checkComponent('VbSelect')">
				<vb-select
					v-model="data[item.field]"
					:id="itemId"
					:type="(item.type || 'select') as any"
					:required="item.required"
					:class="item.class"
					:style="item.style"
					:placeholder="item.placeholder ?? item.label"
					:size="item.size"
					:data="itemData"
					v-bind="item.props"
					v-on="item.listeners"></vb-select>
			</template>
			<template v-else-if="checkComponent('VU') || checkComponent('VbUpload')">
				<vb-upload
					v-model="data[item.field]"
					:id="itemId"
					:required="item.required"
					:class="item.class"
					:style="item.style"
					:placeholder="item.placeholder ?? item.label"
					:size="item.size"
					:data="itemData"
					v-bind="item.props"
					v-on="item.listeners"></vb-upload>
			</template>
			<template v-else-if="checkComponent('Dict') || checkComponent('DictSelect')">
				<dict-select
					v-model="data[item.field]"
					:id="itemId"
					:dictType="item.props?.dictType || ''"
					:type="(item.type || 'select') as any"
					:required="item.required"
					:class="item.class"
					:style="item.style"
					:placeholder="item.placeholder ?? item.label"
					:size="item.size"
					v-bind="item.props"
					v-on="item.listeners"></dict-select>
			</template>
			<template v-else-if="checkComponent('S') || checkComponent('ElSelect')">
				<el-select
					v-model="data[item.field]"
					:id="itemId"
					:required="item.required"
					:class="item.class"
					:style="item.style"
					:placeholder="item.placeholder ?? item.label"
					:size="item.size"
					v-bind="item.props"
					v-on="item.listeners">
					<el-option
						v-for="(select, selectIndex) in itemData"
						:key="selectIndex"
						:value="select.value"
						:label="select.label"
						:class="select.class"
						:disabled="isDisable(select)"
						:style="select.style"></el-option>
				</el-select>
			</template>
			<template v-else-if="checkComponent('R') || checkComponent('ElRadioGroup')">
				<el-radio-group
					v-model="data[item.field]"
					:id="itemId"
					:required="item.required"
					:class="item.class"
					:style="item.style"
					:size="item.size"
					v-bind="item.props"
					v-on="item.listeners">
					<el-radio
						v-for="(radio, radioIndex) in itemData"
						:key="radioIndex"
						:label="radio.value"
						:class="radio.class"
						:style="radio.style"
						:disabled="isDisable(radio)">
						{{ radio.label }}
					</el-radio>
				</el-radio-group>
			</template>
			<template v-else-if="checkComponent('C') || checkComponent('ElCheckboxGroup')">
				<el-checkbox-group
					v-model="data[item.field]"
					:id="itemId"
					:required="item.required"
					:class="item.class"
					:style="item.style"
					:size="item.size"
					v-bind="item.props"
					v-on="item.listeners">
					<el-checkbox
						v-for="(checkbox, checkboxIndex) in itemData"
						:key="checkboxIndex"
						:label="checkbox.value"
						:class="checkbox.class"
						:style="checkbox.style"
						:disabled="isDisable(checkbox)">
						{{ checkbox.label }}
					</el-checkbox>
				</el-checkbox-group>
			</template>
			<template v-else-if="checkComponent('D') || checkComponent('ElDatePicker')">
				<el-date-picker
					v-model="data[item.field]"
					:id="itemId"
					:required="item.required"
					:class="item.class"
					:style="item.style"
					:size="item.size"
					v-bind="item.props"
					v-on="item.listeners"></el-date-picker>
			</template>
			<template v-else-if="checkComponent('VST') || checkComponent('VbSelectTree')">
				<vb-select-tree
					v-model="data[item.field]"
					:id="itemId"
					:required="item.required"
					:data="itemData"
					:placeholder="item.placeholder ?? item.label"
					:class="item.class"
					:style="item.style"
					:size="item.size"
					v-bind="item.props"
					v-on="item.listeners"></vb-select-tree>
			</template>
			<template v-else-if="checkComponent('VE') || checkComponent('VbEditor')">
				<vb-editor
					v-model="data[item.field]"
					:id="itemId"
					:required="item.required"
					:class="item.class"
					:style="item.style"
					:placeholder="item.placeholder ?? item.label"
					:size="item.size"
					:data="itemData"
					v-bind="item.props"
					v-on="item.listeners"></vb-editor>
			</template>
			<template v-else>
				<component
					:is="item.component"
					v-model="data[item.field]"
					v-model:value="data[item.field]"
					:id="itemId"
					:required="item.required"
					:class="item.class"
					:style="item.style"
					:size="item.size"
					:placeholder="item.placeholder ?? item.label"
					v-bind="item.props"
					v-on="item.listeners"></component>
			</template>
		</el-form-item>
	</el-col>
</template>
