<template>
  <view class="form-item" :class="formItemClass">
    <!-- 标签 -->
    <view v-if="label || $slots.label" class="form-item-label" :class="labelClass">
      <slot name="label">
        <text class="label-text">{{ label }}</text>
        <text v-if="required" class="required-mark">*</text>
      </slot>
    </view>
    
    <!-- 内容区域 -->
    <view class="form-item-content" :class="contentClass">
      <slot></slot>
      
      <!-- 错误提示 -->
      <view v-if="showError && errorMessage" class="form-item-error">
        <text class="error-text">{{ errorMessage }}</text>
      </view>
      
      <!-- 帮助文本 -->
      <view v-if="help" class="form-item-help">
        <text class="help-text">{{ help }}</text>
      </view>
    </view>
  </view>
</template>

<script>
import { computed, inject, ref, watch } from 'vue'

export default {
  name: 'FormItem',
  props: {
    // 标签文本
    label: {
      type: String,
      default: ''
    },
    
    // 字段名
    prop: {
      type: String,
      default: ''
    },
    
    // 是否必填
    required: {
      type: Boolean,
      default: false
    },
    
    // 验证规则
    rules: {
      type: Array,
      default: () => []
    },
    
    // 错误信息
    error: {
      type: String,
      default: ''
    },
    
    // 帮助文本
    help: {
      type: String,
      default: ''
    },
    
    // 标签宽度
    labelWidth: {
      type: [String, Number],
      default: ''
    },
    
    // 标签位置
    labelPosition: {
      type: String,
      default: '',
      validator: (value) => ['', 'left', 'right', 'top'].includes(value)
    },
    
    // 是否显示冒号
    colon: {
      type: Boolean,
      default: null
    },
    
    // 验证状态
    validateStatus: {
      type: String,
      default: '',
      validator: (value) => ['', 'success', 'warning', 'error', 'validating'].includes(value)
    },
    
    // 是否显示验证图标
    hasFeedback: {
      type: Boolean,
      default: false
    }
  },
  
  setup(props) {
    // 注入表单实例
    const form = inject('form', null)
    
    // 响应式数据
    const errorMessage = ref(props.error)
    const validating = ref(false)
    
    // 计算属性
    const formItemClass = computed(() => {
      const classes = []
      
      if (props.required) {
        classes.push('is-required')
      }
      
      if (errorMessage.value) {
        classes.push('is-error')
      }
      
      if (props.validateStatus) {
        classes.push(`is-${props.validateStatus}`)
      }
      
      if (validating.value) {
        classes.push('is-validating')
      }
      
      const labelPosition = props.labelPosition || form?.labelPosition || 'right'
      classes.push(`label-${labelPosition}`)
      
      return classes
    })
    
    const labelClass = computed(() => {
      const classes = []
      
      const showColon = props.colon !== null ? props.colon : (form?.colon ?? true)
      if (showColon && props.label) {
        classes.push('has-colon')
      }
      
      return classes
    })
    
    const contentClass = computed(() => {
      const classes = []
      
      if (props.hasFeedback) {
        classes.push('has-feedback')
      }
      
      return classes
    })
    
    const labelStyle = computed(() => {
      const style = {}
      
      const labelWidth = props.labelWidth || form?.labelWidth
      if (labelWidth) {
        style.width = typeof labelWidth === 'number' ? `${labelWidth}px` : labelWidth
      }
      
      return style
    })
    
    const showError = computed(() => {
      return props.validateStatus === 'error' || errorMessage.value
    })
    
    // 验证方法
    const validate = async (trigger = '') => {
      if (!props.prop || !form) return true
      
      const value = form.model[props.prop]
      const rules = [...(props.rules || []), ...(form.rules?.[props.prop] || [])]
      
      if (rules.length === 0) return true
      
      // 过滤触发器匹配的规则
      const filteredRules = trigger 
        ? rules.filter(rule => !rule.trigger || rule.trigger === trigger || 
                              (Array.isArray(rule.trigger) && rule.trigger.includes(trigger)))
        : rules
      
      if (filteredRules.length === 0) return true
      
      validating.value = true
      errorMessage.value = ''
      
      try {
        for (const rule of filteredRules) {
          // 必填验证
          if (rule.required && (value === undefined || value === null || value === '')) {
            throw new Error(rule.message || `${props.label}不能为空`)
          }
          
          // 跳过空值的非必填验证
          if (!rule.required && (value === undefined || value === null || value === '')) {
            continue
          }
          
          // 类型验证
          if (rule.type && !validateType(value, rule.type)) {
            throw new Error(rule.message || `${props.label}格式不正确`)
          }
          
          // 长度验证
          if (rule.min !== undefined || rule.max !== undefined) {
            const len = typeof value === 'string' ? value.length : 
                       Array.isArray(value) ? value.length : 
                       typeof value === 'number' ? value : 0
            
            if (rule.min !== undefined && len < rule.min) {
              throw new Error(rule.message || `${props.label}长度不能少于${rule.min}`)
            }
            
            if (rule.max !== undefined && len > rule.max) {
              throw new Error(rule.message || `${props.label}长度不能超过${rule.max}`)
            }
          }
          
          // 正则验证
          if (rule.pattern && !rule.pattern.test(String(value))) {
            throw new Error(rule.message || `${props.label}格式不正确`)
          }
          
          // 自定义验证器
          if (rule.validator && typeof rule.validator === 'function') {
            await new Promise((resolve, reject) => {
              rule.validator(rule, value, (error) => {
                if (error) {
                  reject(new Error(error))
                } else {
                  resolve()
                }
              })
            })
          }
        }
        
        return true
      } catch (error) {
        errorMessage.value = error.message
        return false
      } finally {
        validating.value = false
      }
    }
    
    // 类型验证
    const validateType = (value, type) => {
      switch (type) {
        case 'string':
          return typeof value === 'string'
        case 'number':
          return typeof value === 'number' && !isNaN(value)
        case 'boolean':
          return typeof value === 'boolean'
        case 'array':
          return Array.isArray(value)
        case 'object':
          return typeof value === 'object' && value !== null && !Array.isArray(value)
        case 'email':
          return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(value))
        case 'url':
          return /^https?:\/\/.+/.test(String(value))
        case 'phone':
          return /^1[3-9]\d{9}$/.test(String(value))
        case 'idcard':
          return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(String(value))
        default:
          return true
      }
    }
    
    // 清除验证
    const clearValidate = () => {
      errorMessage.value = ''
      validating.value = false
    }
    
    // 重置字段
    const resetField = () => {
      if (props.prop && form) {
        form.model[props.prop] = form.initialModel?.[props.prop]
      }
      clearValidate()
    }
    
    // 监听错误信息变化
    watch(() => props.error, (newError) => {
      errorMessage.value = newError
    })
    
    // 向表单注册字段
    if (form && props.prop) {
      form.addField({
        prop: props.prop,
        validate,
        clearValidate,
        resetField
      })
    }
    
    return {
      formItemClass,
      labelClass,
      contentClass,
      labelStyle,
      showError,
      errorMessage,
      validating,
      validate,
      clearValidate,
      resetField
    }
  }
}
</script>

<style lang="scss" scoped>
.form-item {
  margin-bottom: 24px;
  
  &.label-top {
    .form-item-label {
      margin-bottom: 8px;
    }
  }
  
  &.label-left,
  &.label-right {
    display: flex;
    align-items: flex-start;
    
    .form-item-label {
      flex-shrink: 0;
      padding-top: 8px;
    }
    
    .form-item-content {
      flex: 1;
      min-width: 0;
    }
  }
  
  &.label-left {
    .form-item-label {
      margin-right: 12px;
      text-align: left;
    }
  }
  
  &.label-right {
    .form-item-label {
      margin-right: 12px;
      text-align: right;
    }
  }
  
  &.is-required {
    .form-item-label {
      .required-mark {
        color: #f56c6c;
        margin-left: 2px;
      }
    }
  }
  
  &.is-error {
    .form-item-content {
      :deep(.uni-input),
      :deep(.uni-textarea),
      :deep(.uni-picker) {
        border-color: #f56c6c !important;
      }
    }
  }
  
  &.is-success {
    .form-item-content {
      :deep(.uni-input),
      :deep(.uni-textarea),
      :deep(.uni-picker) {
        border-color: #67c23a !important;
      }
    }
  }
  
  &.is-warning {
    .form-item-content {
      :deep(.uni-input),
      :deep(.uni-textarea),
      :deep(.uni-picker) {
        border-color: #e6a23c !important;
      }
    }
  }
  
  &.is-validating {
    .form-item-content {
      position: relative;
      
      &::after {
        content: '';
        position: absolute;
        right: 8px;
        top: 50%;
        transform: translateY(-50%);
        width: 16px;
        height: 16px;
        border: 2px solid #e4e7ed;
        border-top-color: #409eff;
        border-radius: 50%;
        animation: spin 1s linear infinite;
      }
    }
  }
}

.form-item-label {
  font-size: 14px;
  color: #606266;
  line-height: 1.5;
  
  .label-text {
    display: inline-block;
  }
  
  &.has-colon {
    .label-text::after {
      content: ':';
      margin-left: 2px;
    }
  }
}

.form-item-content {
  position: relative;
  
  &.has-feedback {
    padding-right: 32px;
  }
}

.form-item-error {
  margin-top: 4px;
  
  .error-text {
    font-size: 12px;
    color: #f56c6c;
    line-height: 1.4;
  }
}

.form-item-help {
  margin-top: 4px;
  
  .help-text {
    font-size: 12px;
    color: #909399;
    line-height: 1.4;
  }
}

@keyframes spin {
  0% {
    transform: translateY(-50%) rotate(0deg);
  }
  100% {
    transform: translateY(-50%) rotate(360deg);
  }
}
</style>