<template>
  <el-form
    ref="formRef"
    :model="formData"
    :rules="formRules"
    :label-width="labelWidth"
    :label-position="labelPosition"
    :disabled="readonly"
  >
    <el-row :gutter="gutter">
      <el-col
        v-for="field in visibleFields"
        :key="field.id"
        :span="field.span || defaultSpan"
      >
        <el-form-item
          :prop="field.name"
          :label="field.label"
          :required="field.required"
        >
          <template v-if="field.description" #label>
            <span>{{ field.label }}</span>
            <el-tooltip :content="field.description" placement="top">
              <el-icon class="field-description-icon">
                <QuestionFilled />
              </el-icon>
            </el-tooltip>
          </template>

          <!-- 动态渲染字段组件 -->
          <component
            :is="getFieldComponent(field.fieldType)"
            :model-value="formData[field.name]"
            :field="field"
            :readonly="readonly"
            :disabled="isFieldDisabled(field)"
            @update:model-value="handleFieldChange(field.name, $event)"
            @blur="handleFieldBlur(field)"
            @focus="handleFieldFocus(field)"
          />
        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { QuestionFilled } from '@element-plus/icons-vue'
import TextField from './fields/TextField.vue'
import NumberField from './fields/NumberField.vue'
import TextareaField from './fields/TextareaField.vue'
import DateField from './fields/DateField.vue'
import SelectField from './fields/SelectField.vue'
import MultiSelectField from './fields/MultiSelectField.vue'
import BooleanField from './fields/BooleanField.vue'
import TreeSelect from '../common/TreeSelect.vue'
import type { FieldConfig, FormData, FormValidationState, FieldChangeEvent } from '@/types/form'
import { validateField, createValidationRule } from '@/utils/fieldValidator'
import { FieldDependencyManager } from '@/utils/fieldDependency'

interface Props {
  deviceTypeId?: string | number
  fields: FieldConfig[]
  modelValue: FormData
  readonly?: boolean
  labelWidth?: string | number
  labelPosition?: 'left' | 'right' | 'top'
  gutter?: number
  dependencies?: any[]
}

interface Emits {
  (e: 'update:modelValue', value: FormData): void
  (e: 'field-change', event: FieldChangeEvent): void
  (e: 'validation-change', state: FormValidationState): void
}

const props = withDefaults(defineProps<Props>(), {
  readonly: false,
  labelWidth: '120px',
  labelPosition: 'right',
  gutter: 20
})

const emit = defineEmits<Emits>()

const formRef = ref()
const dependencyManager = new FieldDependencyManager()

// 表单数据
const formData = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
})

// 默认栅格占列数
const defaultSpan = computed(() => 24) // 默认占满一行

// 可见字段列表
const visibleFields = computed(() => {
  return props.fields.filter((field) => {
    if (typeof field.visible === 'function') {
      return field.visible(formData.value)
    }
    return field.visible !== false
  })
})

// 表单验证规则
const formRules = computed(() => {
  const rules: any = {}

  props.fields.forEach((field) => {
    if (field.required || field.validationRules) {
      rules[field.name] = []

      // 必填规则
      if (field.required) {
        rules[field.name].push({
          required: true,
          message: `${field.label}不能为空`,
          trigger: ['blur', 'change']
        })
      }

      // 自定义验证规则
      if (field.validationRules) {
        const rule = createValidationRule(field)
        rules[field.name].push(rule)
      }
    }
  })

  return rules
})

/**
 * 获取字段对应的组件
 */
const getFieldComponent = (fieldType: string) => {
  const componentMap: Record<string, any> = {
    text: TextField,
    textarea: TextareaField,
    number: NumberField,
    date: DateField,
    select: SelectField,
    multiselect: MultiSelectField,
    boolean: BooleanField,
    tree: TreeSelect,
    // 兼容API中的字段类型
    url: TextField,
    email: TextField,
    phone: TextField,
    checkbox: BooleanField
  }

  return componentMap[fieldType] || TextField
}

/**
 * 判断字段是否禁用
 */
const isFieldDisabled = (field: FieldConfig): boolean => {
  if (props.readonly) return true
  if (typeof field.disabled === 'function') {
    return field.disabled(formData.value)
  }
  return field.disabled || false
}

/**
 * 处理字段值变化
 */
const handleFieldChange = (fieldName: string, value: any) => {
  const oldValue = formData.value[fieldName]
  const newValue = value

  // 更新表单数据
  formData.value = {
    ...formData.value,
    [fieldName]: newValue
  }

  // 触发联动
  if (dependencyManager) {
    const results = dependencyManager.trigger(fieldName, newValue, formData.value)
    // 处理联动结果
    Object.keys(results).forEach((targetField) => {
      const { type, value: resultValue } = results[targetField]
      if (type === 'setValue' && resultValue !== undefined) {
        formData.value = {
          ...formData.value,
          [targetField]: resultValue
        }
      }
    })
  }

  // 触发字段变更事件
  emit('field-change', {
    fieldName,
    value: newValue,
    oldValue
  })

  // 触发表单验证
  validateField(fieldName)
}

/**
 * 处理字段失焦
 */
const handleFieldBlur = (field: FieldConfig) => {
  // 可以在这里触发验证
  if (formRef.value) {
    formRef.value.validateField(field.name)
  }
}

/**
 * 处理字段聚焦
 */
const handleFieldFocus = (field: FieldConfig) => {
  // 聚焦事件处理
}

/**
 * 验证单个字段
 */
const validateFieldAsync = async (fieldName: string): Promise<boolean> => {
  if (!formRef.value) return false

  try {
    await formRef.value.validateField(fieldName)
    return true
  } catch {
    return false
  }
}

/**
 * 验证整个表单
 */
const validateForm = async (): Promise<boolean> => {
  if (!formRef.value) return false

  try {
    await formRef.value.validate()
    return true
  } catch {
    ElMessage.warning('请检查表单填写是否正确')
    return false
  }
}

/**
 * 重置表单
 */
const resetForm = () => {
  if (!formRef.value) return

  formRef.value.resetFields()

  // 重置为默认值
  const defaultData: FormData = {}
  props.fields.forEach((field) => {
    if (field.defaultValue !== undefined) {
      defaultData[field.name] = field.defaultValue
    }
  })
  formData.value = defaultData
}

/**
 * 清除验证
 */
const clearValidation = () => {
  if (!formRef.value) return
  formRef.value.clearValidate()
}

/**
 * 设置字段值
 */
const setFieldValue = (fieldName: string, value: any) => {
  formData.value = {
    ...formData.value,
    [fieldName]: value
  }
}

/**
 * 获取字段值
 */
const getFieldValue = (fieldName: string) => {
  return formData.value[fieldName]
}

/**
 * 获取表单数据
 */
const getFormData = () => {
  return { ...formData.value }
}

/**
 * 设置表单数据
 */
const setFormData = (data: FormData) => {
  formData.value = { ...data }
}

// 初始化联动配置
watch(
  () => props.dependencies,
  (deps) => {
    if (deps && deps.length > 0) {
      dependencyManager.addDependencies(deps)
    }
  },
  { immediate: true }
)

// 初始化默认值
watch(
  () => props.fields,
  (fields) => {
    const defaultData: FormData = { ...formData.value }
    fields.forEach((field) => {
      if (field.defaultValue !== undefined && formData.value[field.name] === undefined) {
        defaultData[field.name] = field.defaultValue
      }
    })
    if (Object.keys(defaultData).length > 0) {
      formData.value = defaultData
    }
  },
  { immediate: true }
)

// 暴露方法供父组件调用
defineExpose({
  validateField: validateFieldAsync,
  validateForm,
  resetForm,
  clearValidation,
  setFieldValue,
  getFieldValue,
  getFormData,
  setFormData
})
</script>

<style scoped lang="scss">
.field-description-icon {
  margin-left: 4px;
  font-size: 14px;
  color: var(--el-text-color-secondary);
  cursor: help;
}

:deep(.el-form-item__label) {
  font-weight: 500;
}
</style>
