<template>
  <el-form
    ref="formRef"
    :model="localModel"
    :rules="formRules"
    label-width="auto"
    v-bind="$attrs"
    :validate-on-rule-change="false"
  >
    <el-row :gutter="20">
      <el-col
        v-for="item in visibleConfig"
        :key="item.prop"
        :span="item.span || 6"
        :class="{ 'search-form-item': isSearch }"
      >
        <el-form-item
          :label="item.label"
          :prop="item.prop"
          :label-position="item.labelPosition || 'top'"
        >
          <component
            :is="getFieldComponent(item.type)"
            v-bind="getFieldProps(item)"
            @update:model-value="val => handleModelChange(val, item)"
            @focus="() => loadRemoteOptions(item)"
            @filter-change="keyword => handleFilterChange(keyword, item)"
          />
        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
</template>

<script setup>
import { onMounted } from 'vue'
import { useSearchFormLogic } from '@/composables/useSearchFormLogic'

// 字段组件映射
import InputField from './fields/InputField.vue'
import SelectField from './fields/SelectField.vue'
import DateField from './fields/DateField.vue'
import MonthField from './fields/MonthField.vue'
import DateRangeField from './fields/DateRangeField.vue'
import CheckboxGroupField from './fields/CheckboxGroupField.vue'
import TextareaField from './fields/TextareaField.vue'
import UploadField from './fields/UploadField.vue'

const fieldMap = {
  input: InputField,
  select: SelectField,
  date: DateField,
  month: MonthField,
  daterange: DateRangeField,
  'checkbox-group': CheckboxGroupField,
  textarea: TextareaField,
  upload: UploadField
}

const props = defineProps({
  modelValue: { type: Object, default: () => ({}) },
  config: { type: Array, default: () => [] },
  isSearch: { type: Boolean, default: false }
})

const emit = defineEmits([
  'update:modelValue',
  'selectChange',
  'uploadSuccess'
])

const {
  formRef,
  localModel,
  visibleConfig,
  formRules,
  handleModelChange,
  getSelectOptions,
  getDisabledDateFn,
  loadRemoteOptions,
  handleFilterChange,
  remoteLoading,
  init,
  getFormData,
  validate,
  resetForm
} = useSearchFormLogic(props, emit)

// 暴露方法给父组件
defineExpose({ getFormData, validate, resetForm })

// 初始化
onMounted(() => {
  init()
})

// 获取字段组件
function getFieldComponent(type) {
  return fieldMap[type] || 'span'
}

// 构建字段 props
function getFieldProps(item) {
  const base = {
    modelValue: localModel.value[item.prop],
    disabled: item.disabled,
    placeholder: item.placeholder
  }

  switch (item.type) {
    case 'input':
      return {
        ...base,
        inputType: item.inputType,
        decimalDigits: item.decimalDigits
      }
    case 'select':
      return {
        ...base,
        multiple: !!item.multiple,
        clearable: true,
        filterable: true,
        loading: remoteLoading.value[item.prop] || false,
        options: getSelectOptions(item),
        placeholder: item.placeholder || `请选择${item.label}`
      }
    case 'date':
      return {
        ...base,
        valueFormat: item.valueFormat || 'YYYY-MM-DD',
        disabledDate: getDisabledDateFn(item),
        placeholder: `选择${item.label}`
      }
    case 'month':
      return {
        ...base,
        valueFormat: item.valueFormat || 'YYYY-MM',
        disabledDate: getDisabledDateFn(item),
        placeholder: `选择${item.label}`
      }
    case 'daterange':
      return {
        ...base,
        valueFormat: item.valueFormat || 'YYYY-MM-DD',
        disabledDate: getDisabledDateFn(item)
      }
    case 'checkbox-group':
      return {
        ...base,
        options: getSelectOptions(item)
      }
    case 'textarea':
      return {
        ...base,
        clearable: true
      }
    case 'upload':
      return {
        ...base,
        action: item.action,
        headers: item.headers,
        multiple: !!item.multiple,
        limit: item.limit || (item.multiple ? 999 : 1),
        accept: item.accept,
        listType: item.listType || 'text',
        showFileList: item.showFileList,
        uploadType: item.uploadType,
        link: item.link,
        maxSize: item.maxSize
      }
    default:
      return base
  }
}
</script>

<style scoped>
.search-form-item {
  margin-bottom: 20px;
}
</style>