<!-- components/SearchForm.vue -->
<template>
    <el-form :model="formModel" label-width="100px" size="default" label-position="top">
        <el-row :gutter="20">
            <template v-for="item in config" :key="item.prop">
                <!-- Input -->
                <el-col :xs="24" :sm="12" :md="6" :lg="6" v-if="item.type === 'input'">
                    <el-form-item :label="item.label" :prop="item.prop" :rules="item.rules">
                        <el-input :model-value="formModel[item.prop]" @input="(val) => handleNumberInput(val, item)"
                            :placeholder="item.placeholder || `请输入${item.label}`" clearable style="width: 100%" />
                    </el-form-item>
                </el-col>

                <!-- Remote Select (带 api 的 select) -->
                <el-col :xs="24" :sm="12" :md="6" :lg="6" v-else-if="item.type === 'select' && item.api">
                    <el-form-item :label="item.label" :prop="item.prop" :rules="item.rules">
                        <el-select ref="selectRefs[item.prop]" v-model="formModel[item.prop]"
                            :placeholder="item.placeholder || `请选择${item.label}`" clearable filterable
                            :multiple="item.multiple" :loading="item.loading"
                            :no-match-text="item.noMatchText || '无匹配数据'" @filter="handleSelectFilter(item)"
                            @visible-change="handleVisibleChange(item)" @change="(val) => handleChange(item, val)"
                            style="width: 100%">
                            <el-option v-for="opt in item._allOptions" :key="opt[item.valueKey || 'value']"
                                :label="opt[item.labelKey || 'label']" :value="opt[item.valueKey || 'value']" />
                        </el-select>
                    </el-form-item>
                </el-col>

                <!-- Static Select / Dict Select -->
                <el-col :xs="24" :sm="12" :md="6" :lg="6" v-else-if="item.type === 'select'">
                    <el-form-item :label="item.label" :prop="item.prop" :rules="item.rules">
                        <el-select v-model="formModel[item.prop]" :placeholder="item.placeholder || `请选择${item.label}`"
                            clearable :filterable="item.filterable !== false" :multiple="item.multiple"
                            :no-match-text="item.noMatchText || '无匹配数据'">
                            <el-option v-for="opt in item.options" :key="opt[item.valueKey || 'value']"
                                :label="opt[item.labelKey || 'label']" :value="opt[item.valueKey || 'value']" />
                        </el-select>
                    </el-form-item>
                </el-col>

                <!-- Checkbox Group -->
                <el-col :xs="24" :sm="12" :md="6" :lg="6" v-else-if="item.type === 'checkbox-group'">
                    <el-form-item :label="item.label" :prop="item.prop">
                        <el-checkbox-group v-model="formModel[item.prop]">
                            <el-checkbox v-for="opt in item.options" :key="opt[item.valueKey || 'value']"
                                :label="opt[item.valueKey || 'value']">
                                {{ opt[item.labelKey || 'label'] }}
                            </el-checkbox>
                        </el-checkbox-group>
                    </el-form-item>
                </el-col>

                <!-- Date -->
                <el-col :xs="24" :sm="12" :md="6" :lg="6" v-else-if="item.type === 'date'">
                    <el-form-item :label="item.label" :prop="item.prop">
                        <el-date-picker v-model="formModel[item.prop]" type="date"
                            :placeholder="item.placeholder || `请选择${item.label}`" format="YYYY-MM-DD"
                            value-format="YYYY-MM-DD" style="width: 100%" clearable />
                    </el-form-item>
                </el-col>

                <!-- Date Range -->
                <el-col :xs="24" :sm="12" :md="6" :lg="6" v-else-if="item.type === 'daterange'">
                    <el-form-item :label="item.label" :prop="item.prop">
                        <el-date-picker v-model="formModel[item.prop]" type="daterange"
                            :range-separator="item.rangeSeparator || '至'"
                            :start-placeholder="item.startPlaceholder || '开始日期'"
                            :end-placeholder="item.endPlaceholder || '结束日期'" format="YYYY-MM-DD"
                            value-format="YYYY-MM-DD" clearable />
                    </el-form-item>
                </el-col>
            </template>
        </el-row>
    </el-form>
</template>

<script setup>
import { reactive, onMounted, onUnmounted } from 'vue'
import request from '@/utils/request'
import { loadDicts, getDictOptions } from '@/utils/useDict'

const selectRefs = reactive({})

// 新增 handleChange
function handleChange(item, value) {
    // 如果是多选，value 是数组；单选是值
    // 这里不需要处理值，因为 v-model 已绑定

    // 清空 filter 输入框
    nextTick(() => {
        const ref = selectRefs[item.prop]
        if (ref && typeof ref.inputValue === 'string') {
            ref.inputValue = ''
        }
    })
}
// ========================
// 工具函数
// ========================
const formModel = reactive({})
const props = defineProps({
    config: { type: Array, required: true }
})

// 防抖定时器 Map
const debounceMap = new Map()
// 搜索缓存 Map: key = `${prop}:${keyword}`, value = option list
const searchCache = new Map()

// ========================
// 数字输入处理
// ========================
function handleNumberInput(value, item) {
    const { inputType = 'text', decimalDigits = 2 } = item
    if (inputType === 'text') {
        formModel[item.prop] = value
        return
    }

    let result = String(value)
    if (inputType === 'integer') {
        result = result.replace(/[^\d]/g, '')
    } else if (inputType === 'decimal') {
        result = result.replace(/[^\d.]/g, '').replace(/^\./, '')
        const parts = result.split('.')
        if (parts.length > 2) result = parts[0] + '.' + parts.slice(1).join('')
    } else if (inputType === 'signed-decimal') {
        result = result.replace(/[^\d.-]/g, '')
        if (result.startsWith('--')) result = '-' + result.slice(2)
        if (result.includes('-') && !result.startsWith('-')) result = result.replace(/-/g, '')
        result = result.replace(/^\./, '')
        const parts = result.split('.')
        if (parts.length > 2) result = parts[0] + '.' + parts.slice(1).join('')
    }

    if ((inputType === 'decimal' || inputType === 'signed-decimal') && decimalDigits >= 0) {
        const dotIndex = result.indexOf('.')
        if (dotIndex !== -1) {
            const integerPart = result.slice(0, dotIndex)
            let decimalPart = result.slice(dotIndex + 1).slice(0, decimalDigits)
            result = integerPart + (decimalPart ? '.' + decimalPart : '')
        }
    }

    formModel[item.prop] = result
}

// ========================
// 远程选项请求
// ========================
async function fetchOptions(item, keyword = '') {
    const payload = {
        ...(item.requestParams || {}),
        pageNo: item.pageNo || 1,
        pageSize: item.pageSize || 20
    }
    if (keyword) {
        const keyField = item.keywordField || 'keyword'
        payload[keyField] = keyword.trim()
    }

    const res = await request({
        url: item.api,
        method: item.method || 'POST',
        data: payload
    })

    let list = []
    if (typeof item.transform === 'function') {
        list = item.transform(res)
    } else if (res?.data?.records) {
        list = res.data.records
    } else if (res?.data?.list) {
        list = res.data.list
    } else if (Array.isArray(res?.data)) {
        list = res.data
    } else if (res?.data?.data && Array.isArray(res.data.data)) {
        list = res.data.data
    }
    return list
}

// ========================
// 远程搜索逻辑
// ========================
function handleSelectFilter(item, query) {
    // 清除旧防抖
    if (debounceMap.has(item.prop)) {
        clearTimeout(debounceMap.get(item.prop))
    }

    const timer = setTimeout(() => {
        doRemoteSearch(item, query)
    }, item.debounceWait ?? 300)

    debounceMap.set(item.prop, timer)
}

async function doRemoteSearch(item, keyword) {
    const cacheKey = `${item.prop}:${keyword}`
    if (searchCache.has(cacheKey)) {
        item._allOptions = searchCache.get(cacheKey)
        return
    }

    item.loading = true
    try {
        let list = []
        if (!keyword.trim()) {
            list = item._fullOptions || []
        } else {
            list = await fetchOptions(item, keyword)
        }
        item._allOptions = list
        searchCache.set(cacheKey, list)
    } catch (e) {
        console.error(`${item.label} 搜索失败`, e)
        item._allOptions = item._fullOptions || []
    } finally {
        item.loading = false
    }
}

// ========================
// 下拉展开时懒加载全量
// ========================
function handleVisibleChange(item, visible) {
    if (visible && !item._hasLoadedFull) {
        item.loading = true
        fetchOptions(item, '')
            .then(list => {
                item._allOptions = list
                item._fullOptions = list
                item._hasLoadedFull = true
                searchCache.set(`${item.prop}:`, list) // 缓存空关键词
            })
            .catch(e => {
                console.error('加载默认选项失败', e)
                item._allOptions = []
            })
            .finally(() => {
                item.loading = false
            })
    }
}

// ========================
// 初始化
// ========================
onMounted(async () => {
    const dictTypes = []
    const dictItems = []

    for (const item of props.config) {
        // 初始化表单值
        if (['checkbox-group', 'daterange'].includes(item.type)) {
            formModel[item.prop] = item.defaultValue ?? []
        } else {
            formModel[item.prop] = item.defaultValue ?? ''
        }
        if (item.type === 'select' && item.api) {
            item._allOptions = []
            item._fullOptions = []
            item.loading = true
            try {
                const list = await fetchOptions(item, '') // 无关键词，加载默认列表
                item._allOptions = list
                item._fullOptions = list
                item._hasLoadedFull = true
                searchCache.set(`${item.prop}:`, list) // 缓存空关键词结果
            } catch (e) {
                console.error(`预加载 ${item.label} 默认选项失败`, e)
                item._allOptions = []
            } finally {
                item.loading = false
            }
        }
        // 处理数字输入
        if (item.type === 'input' && item.inputType && item.inputType !== 'text') {
            handleNumberInput(formModel[item.prop], item)
        }

        // 收集字典项
        if (item.type === 'select' && item.dictType) {
            dictTypes.push(item.dictType)
            dictItems.push(item)
        }
    }

    // 加载字典
    if (dictTypes.length > 0) {
        await loadDicts(dictTypes)
        for (const item of dictItems) {
            item.options = getDictOptions(item.dictType)
        }
    }
})

// ========================
// 清理
// ========================
onUnmounted(() => {
    debounceMap.forEach(timer => clearTimeout(timer))
    debounceMap.clear()
    searchCache.clear()
})

// ========================
// 暴露方法
// ========================
defineExpose({
    async validate() {
        // 如果你有 el-form ref，可加校验；否则直接返回
        return formModel
    },
    getSearchParams() {
        const params = {}
        for (const key in formModel) {
            const val = formModel[key]
            if (val === '' || val === null || val === undefined) continue
            if (Array.isArray(val) && val.length === 0) continue
            params[key] = val
        }
        return params
    },
    resetForm() {
        props.config.forEach(item => {
            if (['checkbox-group', 'daterange'].includes(item.type)) {
                formModel[item.prop] = []
            } else {
                formModel[item.prop] = ''
            }
        })
    },
    getRawForm() {
        return { ...formModel }
    }
})
</script>