<template>
  <view class="form">
    <block v-for="item in formConfig" :key="item.key">
      <!-- 文本 -->
      <view v-if="item.type === 'input'" v-show="item.visible !== false" class="form_block">
        <gInput
          :ref="(el) => setComponentRef(el, item.key)"
          :label="item.label"
          :readOnly="item.readOnly"
          :placeholder="item.placeholder"
          :required="item.required"
          :errorMsg="item.errorMsg"
          :value="formData[item.key]"
          @inputChange="(e) => onInputChange(e, item.key)"
          @validateRequest="(e) => onValidateRequest({ detail: { key: item.key, value: e.value } })"
        />
      </view>

      <!-- 文本域 -->
      <view v-if="item.type === 'textArea'" v-show="item.visible !== false" class="form_block">
        <gTextArea
          :ref="(el) => setComponentRef(el, item.key)"
          :label="item.label"
          :readOnly="item.readOnly"
          :placeholder="item.placeholder"
          :required="item.required"
          :errorMsg="item.errorMsg"
          :value="formData[item.key]"
          @inputChange="(e) => onInputChange(e, item.key)"
          @validateRequest="(e) => onValidateRequest({ detail: { key: item.key, value: e.value } })"
        />
      </view>

      <!-- 选择 -->
      <view v-if="item.type === 'radio'" v-show="item.visible !== false" class="form_block">
        <gRadio
          :ref="(el) => setComponentRef(el, item.key)"
          :label="item.label"
          :options="item.options"
          :inline="item.inline"
          :readOnly="item.readOnly"
          :required="item.required"
          :errorMsg="item.errorMsg"
          :value="formData[item.key]"
          @radioChange="(e) => onRadioChange(e, item.key)"
          @validateRequest="(e) => onValidateRequest({ detail: { key: item.key, value: e.value } })"
        />
      </view>

      <!-- 短信验证 -->
      <view v-if="item.type === 'smsCode'" v-show="item.visible !== false" class="form_block">
        <gSmsCode
          :ref="(el) => setComponentRef(el, item.key)"
          :phoneLabel="item.phoneLabel"
          :codeLabel="item.codeLabel"
          :sendCodeText="item.sendCodeText"
          :countdownText="item.countdownText"
          :readOnly="item.readOnly"
          :required="item.required"
          :errorMsg="item.errorMsg"
          :phoneValue="formData[item.key + '_phone']"
          :codeValue="formData[item.key + '_code']"
          @phoneInputChange="(e) => onSmsCodePhoneChange(e, item.key)"
          @codeInputChange="(e) => onSmsCodeCodeChange(e, item.key)"
          @sendCodeRequest="(e) => onSmsCodeSendRequest(e, item.key)"
          @validationResult="(e) => handleSmsValidationResult(e, item.key)"
        />
      </view>

      <!-- 省市区选择器 -->
      <view v-if="item.type === 'regionPicker'" v-show="item.visible !== false" class="form_block">
        <gRegionPicker
          :ref="(el) => setComponentRef(el, item.key)"
          :label="item.label"
          :level="item.level"
          :readOnly="item.readOnly"
          :placeholder="item.placeholder"
          :required="item.required"
          :value="formData[item.key]"
          @regionPickerChange="(e) => onRegionPickerChange(e, item.key)"
        />
      </view>

      <!-- 事件触发器 -->
      <view v-if="item.type === 'action'" v-show="item.visible !== false" class="form_block">
        <gAction
          :ref="(el) => setComponentRef(el, item.key)"
          :label="item.label"
          :readOnly="item.readOnly"
          :placeholder="item.placeholder"
          :required="item.required"
          :errorMsg="item.errorMsg"
          :value="formData[item.key]"
          @actionClick="(e) => onActionClick(e, item.key)"
        />
      </view>

    </block>
  </view>
</template>

<script setup lang="ts">
import { ref, defineProps, defineEmits, watch, nextTick, defineExpose } from 'vue';
import gInput from './input/index.vue';
import gTextArea from './textArea/index.vue';
import gRadio from './radio/index.vue';
import gSmsCode from './smsCode/index.vue';
import gRegionPicker from './regionPicker/index.vue';
import gAction from './action/index.vue';

const props = defineProps({
  formConfig: {
    type: Array,
    default: () => []
  },
  formData: {
    type: Object,
    default: () => ({})
  }
});

const emit = defineEmits(['formDataChange', 'smsCodeSendSuccess', 'smsCodeSendFail', 'actionClick', 'errorReport', 'formSubmit']);

const formData = ref({});
const hasError = ref(false);
const componentRefs = ref({});

const setComponentRef = (el, key) => {
  if (el) {
    componentRefs.value[key] = el;
  }
};

watch(() => props.formData, (newVal) => {
  formData.value = { ...newVal };
}, { deep: true, immediate: true });

// [组件]输入框
const onInputChange = (e, key) => {
  const { value } = e;
  const newFormData = { ...formData.value, [key]: value };
  formData.value = newFormData;
  emit('formDataChange', { formData: newFormData, target: { [key]: value } });
};

// [组件]单选框
const onRadioChange = (e, key) => {
  const { value } = e;
  const newFormData = { ...formData.value, [key]: value };
  formData.value = newFormData;
  emit('formDataChange', { formData: newFormData, target: { [key]: value } });
};

// [组件]发送短信验证码
const onSmsCodePhoneChange = (e, key) => {
  const { phoneValue } = e;
  const newFormData = { 
    ...formData.value, 
    [`${key}_phone`]: phoneValue, 
    [`${key}`]: phoneValue 
  };
  formData.value = newFormData;
  emit('formDataChange', { 
    formData: newFormData, 
    target: { 
      [`${key}_phone`]: phoneValue, 
      [`${key}`]: phoneValue } 
    }
  );
};

const onSmsCodeCodeChange = (e, key) => {
  const { codeValue } = e;
  const newFormData = { ...formData.value, [`${key}_code`]: codeValue };
  formData.value = newFormData;
  emit('formDataChange', { formData: newFormData, target: { [`${key}_code`]: codeValue } });
};

const onSmsCodeSendRequest = (e, key) => {
  const { phoneValue } = e;
  const config = props.formConfig.find(item => item.key === key);
  const sendCodeApi = config.sendCodeApi;
  if (sendCodeApi) {
    const validatePhone = config.validatePhone;
    if(validatePhone && !validatePhone(phoneValue)) {
      uni.showModal({
        title: "温馨提示",
        content: config.errorMsg,
        showCancel: false,
      });
      return;
    }
    sendCodeApi(phoneValue)
      .then((res) => {
        const component = componentRefs.value[key];
        if (component && component.startCountdown) {
          component.startCountdown();
        }
        emit('smsCodeSendSuccess', { key, res });
      })
      .catch((err) => {
        emit('smsCodeSendFail', { key, err });
      });
  }
};

const handleSmsValidationResult = (e, key) => {
    const component = componentRefs.value[key];
    if (component && component.handleValidationResult) {
        component.handleValidationResult(e);
    }
}

// [组件]省市区选择器
const onRegionPickerChange = (e, key) => {
  const { code, postcode, value } = e;
  const config = props.formConfig.find(item => item.key === key);
  const newFormData = { 
    ...formData.value, 
    [`${key}`]: e[config.currentBindKey || value],
    [`${key}_regionCode`]: code,
    [`${key}_regionPostCode`]: postcode,
    [`${key}_regionValue`]: value,
  };
  formData.value = newFormData;
  emit('formDataChange', { 
    formData: newFormData, 
    target: { 
      [`${key}`]: e[config.currentBindKey || value],
      [`${key}_regionCode`]: code,
      [`${key}_regionPostCode`]: postcode,
      [`${key}_regionValue`]: value,
    } 
  });
};

// [组件]事件触发器
const onActionClick = (e, key) => {
  const { value } = e;
  const newFormData = { ...formData.value, [key]: value };
  emit('actionClick', { formData: newFormData, target: { [key]: value } })
};

// [辅助]校验
const onValidateRequest = (e) => {
  const { key, value } = e.detail;
  let config;
  let fieldKey;
  if (key.includes('_phone') || key.includes('_code')) {
    const [baseKey, field] = key.split('_');
    config = props.formConfig.find(form => form.key === baseKey);
    fieldKey = field;
  } else {
    config = props.formConfig.find(form => form.key === key);
  }
  
  if (!config) return;

  let isValid = true;
  let validateFunc;
  if (fieldKey === 'phone') {
    validateFunc = config.validatePhone;
  } else if (fieldKey === 'code') {
    validateFunc = config.validateCode;
  } else {
    validateFunc = config.validate;
  }
  
  if (config.required && (
    value === void(0)
    || value === null
    || (typeof value === 'string' && value.trim() === '')
    || (Array.isArray(value) && value.length === 0)
    )) {
    isValid = false;
  } else if (value && typeof validateFunc === 'function' && !validateFunc(value)) {
    isValid = false;
  }
  
  const errorMsg = config.errorMsg;
  const component = componentRefs.value[config.key];
  
  if (component) {
    if (fieldKey) {
        // smsCode 组件内部处理
        component.handleValidationResult({ key: fieldKey, isValid });
    } else {
       // 其他组件暂无直接设置 error 的方法，通常通过 props 或事件反馈，这里简化处理，假设组件不需要显式 error 状态
       // 如果组件需要显示 error 状态，需要在组件内增加 error prop 并传递
    }
  }
  
  if (!isValid) {
    hasError.value = true;
    emit('errorReport', { errorMsg });
  }
};

// [动作]提交
const submitForm = () => {
  hasError.value = false;
  let allValid = true;
  
  props.formConfig.forEach((config) => {
    if (config.enabled === false) { // Assuming explicit false check or check logic
      return;
    }
    
    // 模拟校验逻辑，实际项目中可能需要更完善的校验
    // 这里简单重用 onValidateRequest 的逻辑，但要注意它依赖 componentRefs 和事件
    // 简化：直接检查数据
    
    let isValid = true;
     if (config.type === 'smsCode') {
        const phoneVal = formData.value[`${config.key}_phone`];
        const codeVal = formData.value[`${config.key}_code`];
        
        // Check Phone
        let phoneValid = true;
        if(config.required && !phoneVal) phoneValid = false;
        if(phoneVal && config.validatePhone && !config.validatePhone(phoneVal)) phoneValid = false;
        
        // Check Code
        let codeValid = true;
        if(config.required && !codeVal) codeValid = false;
        if(codeVal && config.validateCode && !config.validateCode(codeVal)) codeValid = false;
        
        if(!phoneValid || !codeValid) isValid = false;
        
        // Trigger validation visual update if needed
        const component = componentRefs.value[config.key];
        if(component) {
             component.handleValidationResult({ key: 'phone', isValid: phoneValid });
             component.handleValidationResult({ key: 'code', isValid: codeValid });
        }

     } else {
        const val = formData.value[config.key];
        if (config.required && (
            val === void(0) || 
            val === null || 
            (typeof val === 'string' && val.trim() === '') || 
            (Array.isArray(val) && val.length === 0)
        )) {
            isValid = false;
        } else if (val && config.validate && !config.validate(val)) {
            isValid = false;
        }
     }
     
     if (!isValid) {
         allValid = false;
         // Trigger visual error if needed (omitted for simplicity as component props usually handle this or errorMsg toast is enough)
         emit('errorReport', { errorMsg: config.errorMsg });
     }
  });

  if (allValid) {
    emit('formSubmit', { formData: formData.value });
  }
};

defineExpose({
  submitForm
});
</script>

<style>
.form {
  width: 100%;
  height: fit-content;
  background-color: #fff;
  padding: 0 20upx;
}

.form .form_block + .form_block {
  border-top: 2upx solid #e5e5e5;
}
</style>
