<template>
  <el-form
    ref="formRef"
    :model="formData"
    :rules="formRules"
    :label-width="labelWidth"
    :label-position="labelPosition"
    :size="size"
    :disabled="disabled"
    :inline="inline"
    v-bind="$attrs"
  >
    <!-- 内联表单 -->
    <template v-if="inline">
      <el-form-item
        v-for="(item, index) in formConfig"
        :key="index"
        :label="item.label"
        :prop="item.name"
        :required="item.req"
        :rules="getItemRules(item)"
      >
        <!-- 输入框 -->
        <el-input
          v-if="item.type === 'text'"
          v-model="formData[item.name]"
          :placeholder="item.placeholder || `请输入${item.label}`"
          :clearable="item.clearable !== false"
          :disabled="item.disabled"
          :maxlength="item.maxlength"
          :show-word-limit="item.showWordLimit"
          v-bind="item.props"
        />

        <!-- 文本域 -->
        <el-input
          v-else-if="item.type === 'textarea'"
          v-model="formData[item.name]"
          type="textarea"
          :placeholder="item.placeholder || `请输入${item.label}`"
          :rows="item.rows || 3"
          :clearable="item.clearable !== false"
          :disabled="item.disabled"
          :maxlength="item.maxlength"
          :show-word-limit="item.showWordLimit"
          v-bind="item.props"
        />

        <!-- 数字输入框 -->
        <el-input-number
          v-else-if="item.type === 'number'"
          v-model="formData[item.name]"
          :placeholder="item.placeholder || `请输入${item.label}`"
          :min="item.min"
          :max="item.max"
          :step="item.step"
          :precision="item.precision"
          :disabled="item.disabled"
          :controls="item.controls !== false"
          v-bind="item.props"
        />

        <!-- 选择器 -->
        <el-select
          v-else-if="item.type === 'select'"
          v-model="formData[item.name]"
          :placeholder="item.placeholder || `请选择${item.label}`"
          :clearable="item.clearable !== false"
          :disabled="item.disabled"
          :multiple="item.multiple"
          :filterable="item.filterable"
          :remote="item.remote"
          :remote-method="item.remoteMethod"
          :loading="item.loading"
          v-bind="item.props"
          :style="inline ? 'width: 180px' : 'width: 100%'"
        >
          <el-option
            v-for="option in getOptions(item)"
            :key="getOptionValue(option, item)"
            :label="getOptionLabel(option, item)"
            :value="getOptionValue(option, item)"
          />
        </el-select>

        <!-- 日期选择器 -->
        <el-date-picker
          v-else-if="item.type === 'date'"
          v-model="formData[item.name]"
          :type="item.dateType || 'date'"
          :placeholder="item.placeholder || `请选择${item.label}`"
          :format="item.format"
          :value-format="item.valueFormat"
          :clearable="item.clearable !== false"
          :disabled="item.disabled"
          :show-time="item.showTime"
          :range-separator="item.rangeSeparator || '至'"
          :start-placeholder="item.startPlaceholder"
          :end-placeholder="item.endPlaceholder"
          v-bind="item.props"
          style="width: 180px"
        />

        <!-- 时间选择器 -->
        <el-time-picker
          v-else-if="item.type === 'time'"
          v-model="formData[item.name]"
          :placeholder="item.placeholder || `请选择${item.label}`"
          :format="item.format"
          :value-format="item.valueFormat"
          :clearable="item.clearable !== false"
          :disabled="item.disabled"
          v-bind="item.props"
          style="width: 180px"
        />

        <!-- 开关 -->
        <el-switch
          v-else-if="item.type === 'switch'"
          v-model="formData[item.name]"
          :disabled="item.disabled"
          :active-text="item.activeText"
          :inactive-text="item.inactiveText"
          :active-value="item.activeValue"
          :inactive-value="item.inactiveValue"
          v-bind="item.props"
        />

        <!-- 单选框组 -->
        <el-radio-group
          v-else-if="item.type === 'radio'"
          v-model="formData[item.name]"
          :disabled="item.disabled"
          v-bind="item.props"
        >
          <el-radio
            v-for="option in getOptions(item)"
            :key="getOptionValue(option, item)"
            :label="getOptionValue(option, item)"
          >
            {{ getOptionLabel(option, item) }}
          </el-radio>
        </el-radio-group>

        <!-- 复选框组 -->
        <el-checkbox-group
          v-else-if="item.type === 'checkbox'"
          v-model="formData[item.name]"
          :disabled="item.disabled"
          v-bind="item.props"
        >
          <el-checkbox
            v-for="option in getOptions(item)"
            :key="getOptionValue(option, item)"
            :label="getOptionValue(option, item)"
          >
            {{ getOptionLabel(option, item) }}
          </el-checkbox>
        </el-checkbox-group>

        <!-- 自定义插槽 -->
        <slot
          v-else-if="item.type === 'slot'"
          :name="item.slotName || item.name"
          :item="item"
          :value="formData[item.name]"
          :formData="formData"
        />

        <!-- 范围选择器 -->
        <div
          v-else-if="item.type === 'range'"
          class="range-input"
          style="display: flex; align-items: center; gap: 10px"
        >
          <el-input
            v-model="formData[item.beginField || 'begin']"
            :placeholder="item.startPlaceholder || '开始值'"
            :clearable="item.clearable !== false"
            :disabled="item.disabled"
            style="flex: 1"
          />
          <span style="color: #999; font-size: 14px">至</span>
          <el-input
            v-model="formData[item.endField || 'end']"
            :placeholder="item.endPlaceholder || '结束值'"
            :clearable="item.clearable !== false"
            :disabled="item.disabled"
            style="flex: 1"
          />
        </div>

        <!-- 默认文本显示 -->
        <span v-else>{{ formData[item.name] }}</span>
      </el-form-item>
    </template>

    <!-- 栅格布局表单 -->
    <el-row v-else :gutter="gutter">
      <el-col
        v-for="(item, index) in formConfig"
        :key="index"
        :span="item.span || 4"
        :xs="item.xs || 12"
        :sm="item.sm || 8"
        :md="item.md || 6"
        :lg="item.lg || 4"
        :xl="item.xl || 4"
      >
        <el-form-item
          :label="item.label"
          :prop="item.name"
          :required="item.req"
          :rules="getItemRules(item)"
        >
          <!-- 输入框 -->
          <el-input
            v-if="item.type === 'text'"
            v-model="formData[item.name]"
            :placeholder="item.placeholder || `请输入${item.label}`"
            :clearable="item.clearable !== false"
            :disabled="item.disabled"
            :maxlength="item.maxlength"
            :show-word-limit="item.showWordLimit"
            v-bind="item.props"
          />

          <!-- 文本域 -->
          <el-input
            v-else-if="item.type === 'textarea'"
            v-model="formData[item.name]"
            type="textarea"
            :placeholder="item.placeholder || `请输入${item.label}`"
            :rows="item.rows || 3"
            :clearable="item.clearable !== false"
            :disabled="item.disabled"
            :maxlength="item.maxlength"
            :show-word-limit="item.showWordLimit"
            v-bind="item.props"
          />

          <!-- 数字输入框 -->
          <el-input-number
            v-else-if="item.type === 'number'"
            v-model="formData[item.name]"
            :placeholder="item.placeholder || `请输入${item.label}`"
            :min="item.min"
            :max="item.max"
            :step="item.step"
            :precision="item.precision"
            :disabled="item.disabled"
            :controls="item.controls !== false"
            v-bind="item.props"
            style="width: 100%"
          />

          <!-- 选择器 -->
          <el-select
            v-else-if="item.type === 'select'"
            v-model="formData[item.name]"
            :placeholder="item.placeholder || `请选择${item.label}`"
            :clearable="item.clearable !== false"
            :disabled="item.disabled"
            :multiple="item.multiple"
            :filterable="item.filterable"
            :remote="item.remote"
            :remote-method="item.remoteMethod"
            :loading="item.loading"
            v-bind="item.props"
            style="width: 100%"
          >
            <el-option
              v-for="option in getOptions(item)"
              :key="getOptionValue(option, item)"
              :label="getOptionLabel(option, item)"
              :value="getOptionValue(option, item)"
            />
          </el-select>

          <!-- 日期选择器 -->
          <el-date-picker
            v-else-if="item.type === 'date'"
            v-model="formData[item.name]"
            :type="item.dateType || 'date'"
            :placeholder="item.placeholder || `请选择${item.label}`"
            :format="item.format"
            :value-format="item.valueFormat"
            :clearable="item.clearable !== false"
            :disabled="item.disabled"
            :show-time="item.showTime"
            :range-separator="item.rangeSeparator || '至'"
            :start-placeholder="item.startPlaceholder"
            :end-placeholder="item.endPlaceholder"
            v-bind="item.props"
            style="width: 100%"
          />

          <!-- 时间选择器 -->
          <el-time-picker
            v-else-if="item.type === 'time'"
            v-model="formData[item.name]"
            :placeholder="item.placeholder || `请选择${item.label}`"
            :format="item.format"
            :value-format="item.valueFormat"
            :clearable="item.clearable !== false"
            :disabled="item.disabled"
            v-bind="item.props"
            style="width: 100%"
          />

          <!-- 开关 -->
          <el-switch
            v-else-if="item.type === 'switch'"
            v-model="formData[item.name]"
            :disabled="item.disabled"
            :active-text="item.activeText"
            :inactive-text="item.inactiveText"
            :active-value="item.activeValue"
            :inactive-value="item.inactiveValue"
            v-bind="item.props"
          />

          <!-- 单选框组 -->
          <el-radio-group
            v-else-if="item.type === 'radio'"
            v-model="formData[item.name]"
            :disabled="item.disabled"
            v-bind="item.props"
          >
            <el-radio
              v-for="option in getOptions(item)"
              :key="getOptionValue(option, item)"
              :label="getOptionValue(option, item)"
            >
              {{ getOptionLabel(option, item) }}
            </el-radio>
          </el-radio-group>

          <!-- 复选框组 -->
          <el-checkbox-group
            v-else-if="item.type === 'checkbox'"
            v-model="formData[item.name]"
            :disabled="item.disabled"
            v-bind="item.props"
          >
            <el-checkbox
              v-for="option in getOptions(item)"
              :key="getOptionValue(option, item)"
              :label="getOptionValue(option, item)"
            >
              {{ getOptionLabel(option, item) }}
            </el-checkbox>
          </el-checkbox-group>

          <!-- 自定义插槽 -->
          <slot
            v-else-if="item.type === 'slot'"
            :name="item.slotName || item.name"
            :item="item"
            :value="formData[item.name]"
            :formData="formData"
          />

          <!-- 范围选择器 -->
          <div
            v-else-if="item.type === 'range'"
            class="range-input"
            style="display: flex; align-items: center; gap: 10px"
          >
            <el-input
              v-model="formData[item.beginField || 'begin']"
              :placeholder="item.startPlaceholder || '开始值'"
              :clearable="item.clearable !== false"
              :disabled="item.disabled"
              style="flex: 1"
            />
            <span style="color: #999; font-size: 14px">至</span>
            <el-input
              v-model="formData[item.endField || 'end']"
              :placeholder="item.endPlaceholder || '结束值'"
              :clearable="item.clearable !== false"
              :disabled="item.disabled"
              style="flex: 1"
            />
          </div>

          <!-- 默认文本显示 -->
          <span v-else>{{ formData[item.name] }}</span>
        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
</template>

<script setup>
import { ref, reactive, watch, computed, onMounted } from "vue";

const props = defineProps({
  // 表单配置
  config: {
    type: Array,
    default: () => [],
  },
  // 表单数据
  modelValue: {
    type: Object,
    default: () => ({}),
  },
  // 标签宽度
  labelWidth: {
    type: String,
    default: "120px",
  },
  // 标签位置
  labelPosition: {
    type: String,
    default: "right",
  },
  // 尺寸
  size: {
    type: String,
    default: "default",
  },
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false,
  },
  // 栅格间距
  gutter: {
    type: Number,
    default: 20,
  },
  // 是否内联表单
  inline: {
    type: Boolean,
    default: false,
  },
});

const emit = defineEmits(["update:modelValue", "change", "validate"]);

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

// 监听父组件传入的modelValue变化，同步到formData
watch(
  () => props.modelValue,
  (newValue) => {
    if (newValue) {
      Object.assign(formData, newValue);
    }
  },
  { immediate: true, deep: true }
);

// 监听formData变化，同步回父组件
watch(
  formData,
  (newData) => {
    emit("update:modelValue", { ...newData });
  },
  { deep: true }
);

// 计算属性
const formConfig = computed(() => props.config);

// 初始化表单数据
const initFormData = () => {
  formConfig.value.forEach((item) => {
    if (formData[item.name] === undefined) {
      formData[item.name] = item.value || getDefaultValue(item.type);
    }
  });
};

// 获取默认值
const getDefaultValue = (type) => {
  const defaults = {
    text: "",
    textarea: "",
    number: null,
    select: null,
    date: null,
    time: null,
    switch: false,
    radio: null,
    checkbox: [],
  };
  return defaults[type] || "";
};

// 初始化表单验证规则
const initFormRules = () => {
  formConfig.value.forEach((item) => {
    if (item.req) {
      formRules[item.name] = [
        { required: true, message: `请输入${item.label}`, trigger: "blur" },
      ];
    }
    if (item.rules) {
      formRules[item.name] = formRules[item.name] || [];
      formRules[item.name].push(...item.rules);
    }
  });
};

// 获取表单项验证规则
const getItemRules = (item) => {
  const rules = [];
  if (item.req) {
    rules.push({
      required: true,
      message: `请输入${item.label}`,
      trigger: "blur",
    });
  }
  if (item.rules) {
    rules.push(...item.rules);
  }
  return rules;
};

// 获取选项数据
const getOptions = (item) => {
  return item.option || [];
};

// 获取选项标签
const getOptionLabel = (option, item) => {
  if (typeof option === "string") return option;
  return option[item.optionLabel] || option.label || option.name || option;
};

// 获取选项值
const getOptionValue = (option, item) => {
  if (typeof option === "string") return option;
  return option[item.optionValue] || option.value || option.id || option;
};

// 监听外部数据变化
watch(
  () => props.modelValue,
  (newVal) => {
    Object.assign(formData, newVal);
  },
  { deep: true, immediate: true }
);

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

// 表单验证
const validate = (callback) => {
  return formRef.value.validate(callback);
};

// 重置表单
const resetFields = () => {
  formRef.value.resetFields();
  // 重置为初始值
  formConfig.value.forEach((item) => {
    formData[item.name] = item.value || getDefaultValue(item.type);
  });
};

// 清除验证
const clearValidate = (props) => {
  formRef.value.clearValidate(props);
};

// 暴露方法
defineExpose({
  validate,
  resetFields,
  clearValidate,
  formRef,
});

// 初始化
onMounted(() => {
  initFormData();
  initFormRules();
});
</script>

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