<template>
  <div class="search-form">
    <el-form
      ref="formRef"
      :model="formData"
      :inline="inline"
      :label-width="labelWidth"
      :size="size"
      @submit.prevent="handleSearch"
    >
      <el-row :gutter="gutter">
        <el-col
          v-for="(item, index) in formItems"
          :key="item.prop || index"
          :span="item.span || defaultSpan"
        >
          <el-form-item
            style="width: 100%"
            :label="item.label"
            :prop="item.prop"
          >
            <!-- 输入框 -->
            <el-input
              v-if="item.type === 'input'"
              v-model="formData[item.prop]"
              :placeholder="item.placeholder || `请输入${item.label}`"
              :clearable="item.clearable !== false"
              :disabled="item.disabled"
              :maxlength="item.maxlength"
              @keyup.enter="handleEnterSearch(item)"
              @clear="handleFieldClear(item)"
            />

            <!-- 选择器 -->
            <el-select
              v-else-if="item.type === 'select'"
              v-model="formData[item.prop]"
              :placeholder="item.placeholder || `请选择${item.label}`"
              :clearable="item.clearable !== false"
              :disabled="item.disabled"
              :multiple="item.multiple"
              :filterable="item.filterable"
              @clear="handleFieldClear(item)"
              @change="handleFieldChange(item, $event)"
            >
              <el-option
                v-for="option in item.options"
                :key="option.value"
                :label="option.label"
                :value="option.value"
                :disabled="option.disabled"
              />
            </el-select>

            <!-- 字典选择器 -->
            <common-selector
              v-else-if="item.type === 'dict-select'"
              v-model="formData[item.prop]"
              :dict-name="item.dictName"
              :label-key="item.labelKey || 'name'"
              :value-key="item.valueKey || 'key'"
              :placeholder="item.placeholder || `请选择${item.label}`"
              :disabled="item.disabled"
              :radio="item.radio"
              @change="handleFieldChange(item, $event)"
            />

            <!-- 日期选择器 -->
            <el-date-picker
              v-else-if="item.type === 'date'"
              v-model="formData[item.prop]"
              :type="item.dateType || 'date'"
              :placeholder="item.placeholder || `请选择${item.label}`"
              :format="item.format"
              :value-format="item.valueFormat"
              :clearable="item.clearable !== false"
              :disabled="item.disabled"
              :start-placeholder="item.startPlaceholder"
              :end-placeholder="item.endPlaceholder"
              @clear="handleFieldClear(item)"
              @change="handleFieldChange(item, $event)"
            />

            <!-- 日期范围选择器 -->
            <el-date-picker
              v-else-if="item.type === 'daterange'"
              v-model="formData[item.prop]"
              type="daterange"
              range-separator="至"
              :start-placeholder="item.startPlaceholder || '开始日期'"
              :end-placeholder="item.endPlaceholder || '结束日期'"
              :format="item.format"
              :value-format="item.valueFormat"
              :clearable="item.clearable !== false"
              :disabled="item.disabled"
              @clear="handleFieldClear(item)"
              @change="handleFieldChange(item, $event)"
            />

            <!-- 单选框组 -->
            <el-radio-group
              v-else-if="item.type === 'radio'"
              v-model="formData[item.prop]"
              :disabled="item.disabled"
              @change="handleFieldChange(item, $event)"
            >
              <el-radio
                v-for="option in item.options"
                :key="option.value"
                :label="option.value"
              >
                {{ option.label }}
              </el-radio>
            </el-radio-group>

            <!-- 复选框组 -->
            <el-checkbox-group
              v-else-if="item.type === 'checkbox'"
              v-model="formData[item.prop]"
              :disabled="item.disabled"
              @change="handleFieldChange(item, $event)"
            >
              <el-checkbox
                v-for="option in item.options"
                :key="option.value"
                :label="option.value"
              >
                {{ option.label }}
              </el-checkbox>
            </el-checkbox-group>

            <!-- 数字输入框 -->
            <el-input-number
              v-else-if="item.type === 'number'"
              v-model="formData[item.prop]"
              :min="item.min"
              :max="item.max"
              :step="item.step || 1"
              :disabled="item.disabled"
              :controls="item.controls !== false"
              @keyup.enter="handleEnterSearch(item)"
              @change="handleFieldChange(item, $event)"
            />

            <!-- 级联选择器 -->
            <el-cascader
              v-else-if="item.type === 'cascader'"
              v-model="formData[item.prop]"
              :options="item.options"
              :props="item.props || {}"
              :clearable="item.clearable !== false"
              :disabled="item.disabled"
              :filterable="item.filterable"
              @clear="handleFieldClear(item)"
              @change="handleFieldChange(item, $event)"
            />

            <!-- 树选择器 -->
            <el-tree-select
              v-else-if="item.type === 'tree'"
              v-model="formData[item.prop]"
              :data="item.data"
              :props="item.props || {}"
              :clearable="item.clearable !== false"
              :disabled="item.disabled"
              :filterable="item.filterable"
              :check-strictly="item.checkStrictly"
              @clear="handleFieldClear(item)"
              @change="handleFieldChange(item, $event)"
            />

            <!-- 自定义插槽 -->
            <slot
              v-else-if="item.type === 'slot'"
              :name="item.slotName || item.prop"
              :prop="item.prop"
              :item="item"
              :value="formData[item.prop]"
              :onChange="(value) => handleSlotChange(item, value)"
            />
          </el-form-item>
        </el-col>

        <!-- 操作按钮 -->
        <el-col :span="buttonSpan || 6">
          <el-form-item>
            <div class="search-form-buttons">
              <el-button type="primary" :icon="Search" @click="handleSearch">
                {{ searchText || "搜索" }}
              </el-button>
              <el-button :icon="RefreshLeft" @click="handleReset">
                {{ resetText || "重置" }}
              </el-button>
            </div>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  </div>
</template>

<script setup>
import { ref, reactive, watch, onMounted } from "vue";
import { Search, RefreshLeft } from "@element-plus/icons-vue";
import CommonSelector from "@/components/CommonSelector.vue";

const props = defineProps({
  // 表单项配置
  items: {
    type: Array,
    default: () => [],
  },
  // 表单数据
  modelValue: {
    type: Object,
    default: () => ({}),
  },
  // 是否行内表单
  inline: {
    type: Boolean,
    default: true,
  },
  // 标签宽度
  labelWidth: {
    type: String,
    default: "auto",
  },
  // 表单尺寸
  size: {
    type: String,
    default: "default",
  },
  // 栅格间隔
  gutter: {
    type: Number,
    default: 16,
  },
  // 默认每个表单项占的列数
  defaultSpan: {
    type: Number,
    default: 6,
  },
  // 按钮列数
  buttonSpan: {
    type: Number,
    default: 6,
  },
  // 搜索按钮文本
  searchText: {
    type: String,
    default: "搜索",
  },
  // 重置按钮文本
  resetText: {
    type: String,
    default: "重置",
  },
  // 是否在重置时自动搜索
  autoSearchOnReset: {
    type: Boolean,
    default: true,
  },
  // 是否在字段清空时自动搜索
  autoSearchOnClear: {
    type: Boolean,
    default: false,
  },
});

const emit = defineEmits([
  "update:modelValue",
  "search",
  "reset",
  "field-change",
  "field-clear",
  "enter-search",
]);

const formRef = ref();
const formData = reactive({});

// 表单项配置
const formItems = props.items;

// 初始化表单数据
const initFormData = () => {
  Object.keys(formData).forEach((key) => {
    delete formData[key];
  });
  formItems.forEach((item) => {
    if (item.prop) {
      if (props.modelValue[item.prop] !== undefined) {
        formData[item.prop] = props.modelValue[item.prop];
      } else {
        formData[item.prop] =
          item.defaultValue !== undefined
            ? item.defaultValue
            : getDefaultValue(item.type);
      }
    }
  });
};

// 获取不同类型的默认值
const getDefaultValue = (type) => {
  switch (type) {
    case "checkbox":
      return [];
    case "number":
      return null;
    case "daterange":
      return [];
    default:
      return "";
  }
};

// 监听表单数据变化
watch(
  formData,
  (newVal) => {
    emit("update:modelValue", { ...newVal });
  },
  { deep: true },
);

// 监听外部数据变化
watch(
  () => props.modelValue,
  (newVal) => {
    Object.keys(newVal).forEach((key) => {
      if (formData.hasOwnProperty(key)) {
        formData[key] = newVal[key];
      }
    });
  },
  { deep: true },
);

// 搜索处理
const handleSearch = () => {
  emit("search", { ...formData });
};

// 重置处理
const handleReset = () => {
  formRef.value?.resetFields();
  initFormData();
  emit("reset", { ...formData });
  if (props.autoSearchOnReset) {
    emit("search", { ...formData });
  }
};

// 字段变化处理
const handleFieldChange = (item, value) => {
  emit("field-change", item.prop, value, formData);
};

// 字段清空处理
const handleFieldClear = (item) => {
  emit("field-clear", item.prop, formData);
  if (props.autoSearchOnClear) {
    emit("search", { ...formData });
  }
};

// 插槽变化处理
const handleSlotChange = (item, value) => {
  formData[item.prop] = value;
  emit("field-change", item.prop, value, formData);
};

// 回车搜索处理
const handleEnterSearch = (item) => {
  emit("enter-search", item.prop, formData);
  // 某些输入框可能需要在回车时触发搜索
  if (item.searchOnEnter !== false) {
    handleSearch();
  }
};

// 暴露方法
defineExpose({
  formRef,
  formData,
  resetFields: handleReset,
  search: handleSearch,
});

onMounted(() => {
  initFormData();
});
</script>

<style lang="less" scoped>
.search-form {
  :deep(.el-form-item) {
    margin-bottom: 16px;
  }

  :deep(.el-form-item__label) {
    font-weight: normal;
  }

  :deep(.el-input),
  :deep(.el-select),
  :deep(.el-date-editor),
  :deep(.el-cascader),
  :deep(.el-tree-select) {
    width: 100%;
  }

  .search-form-buttons {
    display: flex;
    gap: 8px;
  }

  :deep(.el-input-number) {
    width: 100%;
  }

  .el-col-6.is-guttered {
    padding: 0px 24px !important;
  }
}
</style>
