<template>
  <view class="form" :class="formClass">
    <slot></slot>
  </view>
</template>

<script>
import { provide, reactive, ref, computed, onUnmounted } from 'vue'

export default {
  name: 'Form',
  props: {
    // 表单数据对象
    model: {
      type: Object,
      default: () => ({})
    },
    
    // 表单验证规则
    rules: {
      type: Object,
      default: () => ({})
    },
    
    // 标签宽度
    labelWidth: {
      type: [String, Number],
      default: '80px'
    },
    
    // 标签位置
    labelPosition: {
      type: String,
      default: 'right',
      validator: (value) => ['left', 'right', 'top'].includes(value)
    },
    
    // 是否显示标签后的冒号
    colon: {
      type: Boolean,
      default: true
    },
    
    // 表单尺寸
    size: {
      type: String,
      default: 'medium',
      validator: (value) => ['small', 'medium', 'large'].includes(value)
    },
    
    // 是否禁用表单
    disabled: {
      type: Boolean,
      default: false
    },
    
    // 是否显示验证错误信息
    showMessage: {
      type: Boolean,
      default: true
    },
    
    // 是否以内联形式展示表单项
    inline: {
      type: Boolean,
      default: false
    },
    
    // 是否隐藏必填字段的标签旁边的红色星号
    hideRequiredAsterisk: {
      type: Boolean,
      default: false
    }
  },
  
  emits: ['validate'],
  
  setup(props, { emit }) {
    // 表单字段集合
    const fields = ref([])
    
    // 初始表单数据（用于重置）
    const initialModel = reactive({ ...props.model })
    
    // 计算属性
    const formClass = computed(() => {
      const classes = []
      
      classes.push(`form-${props.size}`)
      classes.push(`label-${props.labelPosition}`)
      
      if (props.inline) {
        classes.push('form-inline')
      }
      
      if (props.disabled) {
        classes.push('form-disabled')
      }
      
      if (props.hideRequiredAsterisk) {
        classes.push('hide-required-asterisk')
      }
      
      return classes
    })
    
    // 添加字段
    const addField = (field) => {
      if (field.prop) {
        fields.value.push(field)
      }
    }
    
    // 移除字段
    const removeField = (field) => {
      const index = fields.value.indexOf(field)
      if (index > -1) {
        fields.value.splice(index, 1)
      }
    }
    
    // 验证整个表单
    const validate = async (callback) => {
      let valid = true
      let invalidFields = {}
      
      if (fields.value.length === 0) {
        if (callback) callback(valid, invalidFields)
        return valid
      }
      
      const promises = fields.value.map(async (field) => {
        try {
          const result = await field.validate()
          return { field: field.prop, valid: result }
        } catch (error) {
          return { field: field.prop, valid: false, error: error.message }
        }
      })
      
      const results = await Promise.all(promises)
      
      results.forEach(result => {
        if (!result.valid) {
          valid = false
          invalidFields[result.field] = result.error || '验证失败'
        }
      })
      
      emit('validate', valid, invalidFields)
      
      if (callback) {
        callback(valid, invalidFields)
      }
      
      return valid
    }
    
    // 验证指定字段
    const validateField = async (props, callback) => {
      const propsArray = Array.isArray(props) ? props : [props]
      let valid = true
      let invalidFields = {}
      
      const targetFields = fields.value.filter(field => 
        propsArray.includes(field.prop)
      )
      
      if (targetFields.length === 0) {
        if (callback) callback(valid, invalidFields)
        return valid
      }
      
      const promises = targetFields.map(async (field) => {
        try {
          const result = await field.validate()
          return { field: field.prop, valid: result }
        } catch (error) {
          return { field: field.prop, valid: false, error: error.message }
        }
      })
      
      const results = await Promise.all(promises)
      
      results.forEach(result => {
        if (!result.valid) {
          valid = false
          invalidFields[result.field] = result.error || '验证失败'
        }
      })
      
      if (callback) {
        callback(valid, invalidFields)
      }
      
      return valid
    }
    
    // 重置整个表单
    const resetFields = () => {
      fields.value.forEach(field => {
        field.resetField()
      })
    }
    
    // 清除验证信息
    const clearValidate = (props) => {
      if (props) {
        const propsArray = Array.isArray(props) ? props : [props]
        fields.value
          .filter(field => propsArray.includes(field.prop))
          .forEach(field => field.clearValidate())
      } else {
        fields.value.forEach(field => field.clearValidate())
      }
    }
    
    // 滚动到第一个错误字段
    const scrollToField = (prop) => {
      const field = fields.value.find(field => field.prop === prop)
      if (field && field.$el) {
        field.$el.scrollIntoView({
          behavior: 'smooth',
          block: 'center'
        })
      }
    }
    
    // 提供给子组件的数据和方法
    provide('form', {
      model: props.model,
      rules: props.rules,
      labelWidth: props.labelWidth,
      labelPosition: props.labelPosition,
      colon: props.colon,
      size: props.size,
      disabled: props.disabled,
      showMessage: props.showMessage,
      hideRequiredAsterisk: props.hideRequiredAsterisk,
      initialModel,
      addField,
      removeField
    })
    
    // 清理
    onUnmounted(() => {
      fields.value = []
    })
    
    return {
      formClass,
      fields,
      validate,
      validateField,
      resetFields,
      clearValidate,
      scrollToField
    }
  }
}
</script>

<style lang="scss" scoped>
.form {
  &.form-inline {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    
    :deep(.form-item) {
      display: inline-flex;
      margin-right: 16px;
      margin-bottom: 0;
      vertical-align: top;
      
      .form-item-label {
        white-space: nowrap;
      }
      
      .form-item-content {
        display: inline-block;
        vertical-align: top;
      }
    }
  }
  
  &.form-disabled {
    :deep(.form-item) {
      .form-item-label {
        color: #c0c4cc;
      }
    }
  }
  
  &.hide-required-asterisk {
    :deep(.form-item) {
      .required-mark {
        display: none;
      }
    }
  }
  
  &.form-small {
    :deep(.form-item) {
      margin-bottom: 18px;
      
      .form-item-label {
        font-size: 12px;
      }
      
      .uni-input,
      .uni-textarea,
      .uni-picker {
        font-size: 12px;
        padding: 6px 8px;
      }
    }
  }
  
  &.form-medium {
    :deep(.form-item) {
      margin-bottom: 22px;
      
      .form-item-label {
        font-size: 14px;
      }
      
      .uni-input,
      .uni-textarea,
      .uni-picker {
        font-size: 14px;
        padding: 8px 12px;
      }
    }
  }
  
  &.form-large {
    :deep(.form-item) {
      margin-bottom: 26px;
      
      .form-item-label {
        font-size: 16px;
      }
      
      .uni-input,
      .uni-textarea,
      .uni-picker {
        font-size: 16px;
        padding: 10px 16px;
      }
    }
  }
}
</style>