<template>
    <view :class="[
        `im-form--${layout}`,
        `im-form--${size}`,
        {
            'im-form--disabled': disabled,
            'im-form--readonly': readonly,
            'im-form--colon': colon
        }
    ]" :style="[customStyle]" class="im-form" @submit.prevent="handleSubmit">
        <!-- 表单内容 -->
        <slot />

        <!-- 提交按钮插槽 -->
        <slot name="submit" :submit="handleSubmit" :validate="validate" :reset="handleReset">
            <!-- 默认提交按钮 -->
            <view v-if="showDefaultSubmit" class="im-form__actions">
                <im-button type="primary" :disabled="disabled || submitting" @click="handleSubmit" :size="size" block>
                    {{ submitText }}
                </im-button>
                <im-button v-if="showReset" :disabled="disabled || submitting" @click="handleReset" :size="size" block>
                    {{ resetText }}
                </im-button>
            </view>
        </slot>
    </view>
</template>

<script setup lang="ts">
import {
    ref,
    reactive,
    provide,
    watch
} from 'vue'
import type {
    FormProps,
    FormEmits,
    FormContext,
    FormModel,
    FormErrors,
    ValidateResult
} from '../../types/components/form'
import { validateRule } from './rules'

const props = withDefaults(defineProps<FormProps & {
    // 提交相关
    submitText?: string
    resetText?: string
    showDefaultSubmit?: boolean
    showReset?: boolean
    validateOnSubmit?: boolean
    scrollToFirstError?: boolean
}>(), {
    modelValue: () => ({}),
    layout: 'vertical',
    size: 'medium',
    labelWidth: undefined,
    labelAlign: 'right',
    colon: true,
    disabled: false,
    readonly: false,
    showValidateStatus: true,
    hideRequiredMark: false,
    validateOnChange: true,
    validateOnBlur: true,
    validateOnSubmit: true,
    scrollToFirstError: false,
    customStyle: () => ({}),
    // 提交相关默认值
    submitText: '提交',
    resetText: '重置',
    showDefaultSubmit: true,
    showReset: true,
})

const emit = defineEmits<FormEmits>()

// 响应式数据
const formModel = reactive<FormModel>({ ...props.modelValue })
const formErrors = reactive<FormErrors>({})
const formRules = reactive<Record<string, any[]>>({})
const formFields = reactive<Record<string, any>>({})
const submitting = ref(false)

// 监听外部 modelValue 变化
watch(
    () => props.modelValue,
    (newModel) => {
        Object.keys(formModel).forEach(key => {
            delete formModel[key]
        })
        Object.assign(formModel, newModel)
    },
    { deep: true }
)

// 注册字段
const addField = (prop: string, field: any) => {
    if (prop) {
        formFields[prop] = field

        // 初始化字段值
        if (formModel[prop] === undefined) {
            formModel[prop] = field.value || ''
        }
    }
}

// 移除字段
const removeField = (prop: string) => {
    if (prop && formFields[prop]) {
        delete formFields[prop]
    }
}

// 验证单个字段
const validateField = async (prop: string): Promise<boolean> => {
    const field = formFields[prop]
    if (!field || !field.rules) {
        delete formErrors[prop]
        return true
    }

    const value = formModel[prop]
    const rules = Array.isArray(field.rules) ? field.rules : [field.rules]

    for (const rule of rules) {
        // 这里需要导入 validateRule 函数
        const result = await validateRule(value, rule)
        if (typeof result === 'string') {
            formErrors[prop] = result
            return false
        }
    }

    delete formErrors[prop]
    return true
}

// 验证所有字段
const validate = async (): Promise<ValidateResult> => {
    const errors: FormErrors = {}
    const fields: Record<string, boolean> = {}
    let valid = true

    const fieldNames = Object.keys(formFields)

    for (const prop of fieldNames) {
        const fieldValid = await validateField(prop)
        fields[prop] = fieldValid

        if (!fieldValid && formErrors[prop]) {
            errors[prop] = formErrors[prop]
            valid = false

            // 滚动到第一个错误项
            if (props.scrollToFirstError && !firstErrorField.value) {
                firstErrorField.value = prop
                scrollToField(prop)
            }
        }
    }

    const result: ValidateResult = { valid, errors, fields }
    emit('validate', result)

    if (!valid) {
        emit('error', errors)
    }

    return result
}

// 重置字段
const resetField = (prop: string) => {
    const field = formFields[prop]
    if (field) {
        formModel[prop] = field.initialValue || ''
        delete formErrors[prop]
    }
}

// 重置表单
const handleReset = (values?: any) => {
    Object.keys(formFields).forEach(prop => {
        resetField(prop)
    })
    emit('update:modelValue', values || {})
    emit('reset')
}

// 清空验证
const clearValidate = (prop?: string) => {
    if (prop) {
        delete formErrors[prop]
    } else {
        Object.keys(formErrors).forEach(key => {
            delete formErrors[key]
        })
    }
}

// 处理提交
const handleSubmit = async (event?: Event) => {
    event?.preventDefault?.()
    submitting.value = true

    try {
        let isValid = true

        if (props.validateOnSubmit) {
            const result = await validate()
            isValid = result.valid
        }

        if (isValid) {
            emit('submit', { ...formModel })
        }
    } finally {
        submitting.value = false
    }
}

// 滚动到错误字段
const firstErrorField = ref<string>('')
const scrollToField = (prop: string) => {
    const field = formFields[prop]
    if (field && field.$el) {
        // 在小程序中可能需要使用 uni.pageScrollTo
        // #ifdef MP-WEIXIN || MP-ALIPAY
        uni.pageScrollTo({
            scrollTop: field.$el.offsetTop - 100,
            duration: 300
        })
        // #endif
    }
}

// 提供表单上下文
const formContext: FormContext = {
    model: formModel,
    rules: formRules,
    errors: formErrors,
    layout: props.layout,
    size: props.size,
    labelWidth: props.labelWidth,
    labelAlign: props.labelAlign,
    colon: props.colon,
    disabled: props.disabled,
    readonly: props.readonly,
    showValidateStatus: props.showValidateStatus,
    hideRequiredMark: props.hideRequiredMark,
    validateOnChange: props.validateOnChange,
    validateOnBlur: props.validateOnBlur,
    addField,
    removeField,
    validateField,
    resetField,
    clearValidate
}

provide('imForm', formContext)

// 暴露方法
defineExpose({
    validate,
    reset: handleReset,
    clearValidate,
    submit: handleSubmit,
    getModel: () => ({ ...formModel }),
    setModel: (values: FormModel) => {
        emit('update:modelValue', values)
    },
    setFieldValue: (prop: string, value: any) => {
        if (prop in formModel) {
            formModel[prop] = value
        }
    },
    getFieldValue: (prop: string) => {
        return formModel[prop]
    }
})
</script>

<style lang="scss" scoped>
.im-form {
    width: 100%;
    box-sizing: border-box;

    // 布局
    // &--vertical {
    //     .im-form-item {
    //         margin-bottom: 32rpx;
    //     }
    // }

    // &--horizontal {
    //     display: flex;
    //     flex-wrap: wrap;
    //     gap: 10rpx;

    //     .im-form-item {
    //         flex: 1;
    //         min-width: 200rpx;
    //     }
    // }

    // &--inline {
    //     display: flex;
    //     align-items: center;
    //     flex-wrap: wrap;
    //     gap: 16rpx;

    //     .im-form-item {
    //         margin-bottom: 0;
    //         display: inline-flex;
    //         align-items: center;
    //     }
    // }

    // 大小
    // &--small {
    //     .im-form-item {
    //         font-size: 24rpx;
    //     }
    // }

    // &--medium {
    //     .im-form-item {
    //         font-size: 28rpx;
    //     }
    // }

    // &--large {
    //     .im-form-item {
    //         font-size: 32rpx;
    //     }
    // }

    // 禁用状态
    &--disabled {
        opacity: 0.6;
        cursor: not-allowed;

        .im-form-item__content {
            pointer-events: none;
        }
    }

    // 操作按钮区域
    &__actions {
        display: flex;
        gap: 24rpx;
        margin-top: 48rpx;
        padding-top: 32rpx;
        border-top: 1rpx solid #f0f0f0;

        .im-form--horizontal & {
            width: 100%;
        }
    }

    // &__submit-btn,
    // &__reset-btn {
    //     flex: 1;
    //     border: none;
    //     border-radius: 8rpx;
    //     font-weight: 500;
    //     transition: all 0.2s ease;

    //     &:active {
    //         opacity: 0.8;
    //     }

    //     &:disabled {
    //         opacity: 0.6;
    //         cursor: not-allowed;
    //     }
    // }

    // &__submit-btn {
    //     background: #07c160;
    //     color: #ffffff;

    //     &--small {
    //         padding: 16rpx 24rpx;
    //         font-size: 24rpx;
    //     }

    //     &--medium {
    //         padding: 20rpx 32rpx;
    //         font-size: 28rpx;
    //     }

    //     &--large {
    //         padding: 24rpx 40rpx;
    //         font-size: 32rpx;
    //     }
    // }

    // &__reset-btn {
    //     background: #ffffff;
    //     color: #666666;
    //     border: 1rpx solid #dcdee0;

    //     &--small {
    //         padding: 16rpx 24rpx;
    //         font-size: 24rpx;
    //     }

    //     &--medium {
    //         padding: 20rpx 32rpx;
    //         font-size: 28rpx;
    //     }

    //     &--large {
    //         padding: 24rpx 40rpx;
    //         font-size: 32rpx;
    //     }
    // }
}
</style>