/**
 * 表单验证组合式函数
 */

import { ref, reactive, computed } from 'vue'
import { ElMessage } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'

/**
 * 使用表单验证
 */
export const useFormValidation = <T extends Record<string, any>>(
  initialData: T,
  rules: FormRules
) => {
  const formRef = ref<FormInstance>()
  const formData = reactive<T>({ ...initialData })
  const errors = ref<Record<string, string>>({})
  const isValidating = ref(false)

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

    try {
      isValidating.value = true
      await formRef.value.validate()
      errors.value = {}
      return true
    } catch (error) {
      console.error('表单验证失败:', error)
      return false
    } finally {
      isValidating.value = false
    }
  }

  /**
   * 验证指定字段
   */
  const validateField = async (field: keyof T): Promise<boolean> => {
    if (!formRef.value) return false

    try {
      await formRef.value.validateField(field as string)
      delete errors.value[field as string]
      return true
    } catch (error) {
      errors.value[field as string] = error as string
      return false
    }
  }

  /**
   * 清除验证结果
   */
  const clearValidation = (fields?: (keyof T)[]) => {
    if (!formRef.value) return

    if (fields) {
      formRef.value.clearValidate(fields as string[])
      fields.forEach(field => {
        delete errors.value[field as string]
      })
    } else {
      formRef.value.clearValidate()
      errors.value = {}
    }
  }

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

    formRef.value.resetFields()
    Object.assign(formData, initialData)
    errors.value = {}
  }

  /**
   * 设置字段错误
   */
  const setFieldError = (field: keyof T, message: string) => {
    errors.value[field as string] = message
  }

  /**
   * 清除字段错误
   */
  const clearFieldError = (field: keyof T) => {
    delete errors.value[field as string]
  }

  /**
   * 获取字段错误
   */
  const getFieldError = (field: keyof T) => {
    return errors.value[field as string]
  }

  /**
   * 检查表单是否有错误
   */
  const hasErrors = computed(() => {
    return Object.keys(errors.value).length > 0
  })

  /**
   * 检查表单是否有效
   */
  const isValid = computed(() => {
    return !hasErrors.value && !isValidating.value
  })

  return {
    formRef,
    formData,
    errors: computed(() => errors.value),
    isValidating: computed(() => isValidating.value),
    hasErrors,
    isValid,
    validateForm,
    validateField,
    clearValidation,
    resetForm,
    setFieldError,
    clearFieldError,
    getFieldError
  }
}

/**
 * 常用验证规则
 */
export const validationRules = {
  /**
   * 必填验证
   */
  required: (message = '此字段为必填项') => ({
    required: true,
    message,
    trigger: 'blur'
  }),

  /**
   * 邮箱验证
   */
  email: (message = '请输入正确的邮箱格式') => ({
    type: 'email' as const,
    message,
    trigger: 'blur'
  }),

  /**
   * 手机号验证
   */
  phone: (message = '请输入正确的手机号格式') => ({
    pattern: /^1[3-9]\d{9}$/,
    message,
    trigger: 'blur'
  }),

  /**
   * 长度验证
   */
  length: (min: number, max: number, message?: string) => ({
    min,
    max,
    message: message || `长度必须在${min}-${max}位之间`,
    trigger: 'blur'
  }),

  /**
   * 最小长度验证
   */
  minLength: (min: number, message?: string) => ({
    min,
    message: message || `长度不能少于${min}位`,
    trigger: 'blur'
  }),

  /**
   * 最大长度验证
   */
  maxLength: (max: number, message?: string) => ({
    max,
    message: message || `长度不能超过${max}位`,
    trigger: 'blur'
  }),

  /**
   * 正则验证
   */
  pattern: (pattern: RegExp, message: string) => ({
    pattern,
    message,
    trigger: 'blur'
  }),

  /**
   * 自定义验证
   */
  custom: (validator: (rule: any, value: any, callback: any) => void) => ({
    validator,
    trigger: 'blur'
  }),

  /**
   * 账号验证（字母数字下划线）
   */
  account: (message = '账号只能包含字母、数字和下划线，长度4-20位') => ({
    pattern: /^[a-zA-Z0-9_]{4,20}$/,
    message,
    trigger: 'blur'
  }),

  /**
   * 密码验证
   */
  password: (min = 6, max = 20, message?: string) => ({
    min,
    max,
    message: message || `密码长度必须在${min}-${max}位之间`,
    trigger: 'blur'
  }),

  /**
   * 确认密码验证
   */
  confirmPassword: (passwordField: string, message = '两次输入的密码不一致') => ({
    validator: (rule: any, value: any, callback: any) => {
      if (!value) {
        callback(new Error('请再次输入密码'))
        return
      }
      // 这里需要访问表单数据，在实际使用时需要传入表单数据
      callback()
    },
    trigger: 'blur'
  })
}

/**
 * 使用实时验证
 */
export const useRealtimeValidation = <T extends Record<string, any>>(
  formData: T,
  rules: FormRules
) => {
  const errors = ref<Record<string, string>>({})
  const validFields = ref<Set<string>>(new Set())

  /**
   * 验证单个字段
   */
  const validateField = async (field: keyof T, value: any) => {
    const fieldRules = rules[field as string]
    if (!fieldRules) return true

    try {
      // 这里简化处理，实际应该使用async-validator
      const ruleArray = Array.isArray(fieldRules) ? fieldRules : [fieldRules]
      
      for (const rule of ruleArray) {
        if (rule.required && (!value || value === '')) {
          throw new Error(rule.message || '此字段为必填项')
        }
        
        if (rule.min && value && value.length < rule.min) {
          throw new Error(rule.message || `长度不能少于${rule.min}位`)
        }
        
        if (rule.max && value && value.length > rule.max) {
          throw new Error(rule.message || `长度不能超过${rule.max}位`)
        }
        
        if (rule.pattern && value && !rule.pattern.test(value)) {
          throw new Error(rule.message || '格式不正确')
        }
      }

      delete errors.value[field as string]
      validFields.value.add(field as string)
      return true
    } catch (error: any) {
      errors.value[field as string] = error.message
      validFields.value.delete(field as string)
      return false
    }
  }

  /**
   * 检查所有字段是否有效
   */
  const isAllValid = computed(() => {
    const requiredFields = Object.keys(rules)
    return requiredFields.every(field => validFields.value.has(field)) &&
           Object.keys(errors.value).length === 0
  })

  return {
    errors: computed(() => errors.value),
    validFields: computed(() => validFields.value),
    isAllValid,
    validateField
  }
}
