<template>
  <view class="dynamic-form">
    <u-form ref="formRef" :model="form" @submit="submitForm" :rules="rules">
      <slot name="top"></slot>

      <template v-if="step2">
        <slot name="bottom"></slot>
        <slot name="transferAmount"></slot>
        <view v-for="(group, groupKey) in groupedFields" :key="groupKey">
          <view class="form-group">
            <text class="form-label1">{{ getGroupTitle(groupKey) }}</text>
          </view>
          <view v-for="field in group" :key="field.fieldName" class="form-group">
            <template v-if="!isNoList.includes(field.fieldName)">
              <!-- 输入框 -->
              <cwg-input :rulesKey="field.fieldName" :label="tFieldTitle(field)" :required="field.required"
                v-if="field.fieldType === 'input'" v-model:value="form[field.fieldName]" :fkey="field.fieldName"
                type="text" :placeholder="tDescription(field)" :disabled="!!field.fixedValue"
                @change="clearFieldValidate(field)" />
              <!-- 数字 -->
              <cwg-input :rulesKey="field.fieldName" :label="tFieldTitle(field)" :required="field.required"
                v-else-if="field.fieldType === 'number'" v-model:value="form[field.fieldName]" :fkey="field.fieldName"
                type="number" :placeholder="tDescription(field)" :disabled="!!field.fixedValue" />

              <!-- 日期 -->
              <cwg-input :rulesKey="field.fieldName" :label="tFieldTitle(field)" :required="field.required"
                v-else-if="field.fieldType === 'date'" v-model:value="form[field.fieldName]" :fkey="field.fieldName"
                type="date" :placeholder="tDescription(field)" @change="clearFieldValidate(field)" />
              <!-- 下拉选择 -->
              <cwg-input :rulesKey="field.fieldName" :label="tFieldTitle(field)" :required="field.required"
                v-else-if="field.fieldType === 'select'" v-model:value="form[field.fieldName]" :fkey="field.fieldName"
                type="select" :columns="field.availableDtos.map(i => ({ text: i.value, value: i.valueId }))"
                :placeholder="tDescription(field)" @change="clearFieldValidate(field)" />
              <!-- 文件上传 -->
              <template v-else-if="field.fieldType === 'file'">
                <cwg-input :rulesKey="field.fieldName" :label="tFieldTitle(field)" :required="field.required"
                  v-model:value="form[field.fieldName]" :fkey="field.fieldName" type="upload"
                  :accept="'.jpg,.jpeg,.png,.pdf'" :is-upload-d="true" @change="onFileChange(field, $event)">
                  <view class="cwg-upload">
                    <u-icon name="folder" />
                    <text class="name">{{ tFieldDescription(field) }}</text>
                    <text class="back">{{ t('card.New1.d4') }}</text>
                  </view>
                </cwg-input>

                <view>
                  <text class="pdf-link" v-if="form[field.fieldName] && isPdf(form[field.fieldName])"
                    @tap="previewFile(form[field.fieldName + 'Value']?.[0]?.url)">
                    {{ getFileName(form[field.fieldName]) }}
                  </text>
                </view>
              </template>

              <!-- 未支持 -->
              <view v-else>
                未支持类型：{{ field.fieldType }}
              </view>

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


      <slot name="tips"></slot>
      <slot v-if="step2" name="submit"></slot>
    </u-form>
  </view>
</template>

<script setup>
import { reactive, ref, computed, watch, nextTick, onMounted } from "vue";
import dayjs from "dayjs";
import { showToast } from "@/utils/toast";
import { useI18n } from "vue-i18n";
import { uploadApi } from "@/api/upload";
import Config from "@/config";
const { Host00 } = Config;
const isNoList = ['payoutMethod', 'transferType', 'payoutCurrency', 'transferAmount', 'senderAddress', 'senderDateOfBirth', 'senderCity', 'senderCountry', 'senderNationality']

// props
const props = defineProps({
  fields: Array,
  globalForm: Object,
  step2: Boolean
});

// emit
const emit = defineEmits(["submit", "validate"]);
const formRef = ref();

// i18n
const { t } = useI18n();

const getGroupTitle = (type) => {
  const map = {
    common: "global.GlobalOrder.common",
    receiver: "global.GlobalOrder.receiver",
    sender: "global.GlobalOrder.sender",
    other: "global.GlobalOrder.other",
  };
  return t(map[type] || type);
}

// -----------------------------------------------------
// 1️⃣ form 本地 copy（解决父组件传值无回显）
// -----------------------------------------------------
const form = ref({ ...props.globalForm });
watch(
  () => props.globalForm,
  (val) => {
    Object.keys(val).forEach(key => {
      form.value[key] = val[key]
      if (typeof val[key] === 'string' && val[key].startsWith('/wasabi')) {
        form.value[key + 'Value'] = [{ url: Host00 + val[key] }]
      }
    })
  },
  { deep: true, immediate: true }
)

// 子组件更新 → 同步到父组件
watch(
  form,
  (val) => {
    Object.assign(props.globalForm, val);
  },
  { deep: true, immediate: true }
);

// -----------------------------------------------------
// 校验规则
// -----------------------------------------------------
const rules = ref({});

// -----------------------------------------------------
// 字段初始化回显 (相当于Vue2中的watch fields)
// -----------------------------------------------------
watch(
  () => props.fields,
  (newFields) => {
    if (!newFields || !Array.isArray(newFields)) return;

    const newRules = {};
    newFields.forEach((field) => {
      // 有 fixedValue 时回显
      if (field.fieldType == 'file') {
        props.globalForm[field.fieldName] = field.rfiValueUrl;
      } else if (field.fixedValue !== undefined && field.fixedValue !== null) {
        props.globalForm[field.fieldName] = field.fixedValue;
      } else if (field.rfiValue !== undefined && field.rfiValue !== null) {
        props.globalForm[field.fieldName] = field.rfiValue;
      } else if (!(field.fieldName in props.globalForm)) {
        // 没有则初始化为空
        props.globalForm[field.fieldName] = null;
      }

      // 设置校验规则
      newRules[field.fieldName] = getRules(field);
    });

    // 更新规则对象
    rules.value = newRules;

    nextTick(() => {
      if (formRef.value && formRef.value.clearValidate) {
        formRef.value.clearValidate();
      }
    });
  },
  { immediate: true, deep: true }
);

// -----------------------------------------------------
// 多语言
// -----------------------------------------------------
const tFieldTitle = (f) =>
  t(`global.fieldName.${f.fieldName}.fieldTitle`) || f.fieldTitle;

const tFieldDescription = (f) =>
  t(`global.fieldName.${f.fieldName}.fieldDescription`) || f.fieldDescription;

const tDescription = (f) =>
  t(`global.fieldName.${f.fieldName}.fieldDescription`) || f.fieldDescription;

// -----------------------------------------------------
// 分组排序
// -----------------------------------------------------
const order = { common: 1, sender: 2, receiver: 3 };
const groupedFields = computed(() => {
  // 先排序
  const sorted = props.fields
    .slice()
    .sort((a, b) => {
      const o1 = order[a.customerType] || 99;
      const o2 = order[b.customerType] || 99;
      if (o1 !== o2) return o1 - o2;
      return (a.sorting || 0) - (b.sorting || 0);
    });

  // 分组
  const groupsMap = {};
  sorted.forEach((f) => {
    const key = f.fieldUserType || f.customerType || "other";
    if (!groupsMap[key]) groupsMap[key] = [];
    groupsMap[key].push(f);
  });

  // 按固定顺序生成最终 groups
  const groupOrder = ["sender", "receiver"];
  const groups = {};
  groupOrder.forEach((key) => {
    if (groupsMap[key]) {
      groups[key] = groupsMap[key];
    }
  });
  return groups;
});

// -----------------------------------------------------
// 校验
// -----------------------------------------------------
const getRules = (field) => {
  const fieldRules = [];

  if (field.required) {
    fieldRules.push({
      required: true,
      message: tFieldTitle(field) + t("global.GlobalOrder.RulesRequire"),
      trigger: ['blur', 'change']
    });
  }

  if (field.regex) {
    try {
      fieldRules.push({
        pattern: new RegExp(field.regex),
        message: tFieldTitle(field) + t("global.GlobalOrder.RulesReg"),
        trigger: ['blur', 'change']
      });
    } catch (e) {
      console.warn('正则表达式解析失败:', field.regex, e);
    }
  }

  return fieldRules;
};

const clearFieldValidate = (field) => {
  nextTick(() => {
    if (formRef.value && formRef.value.validateField) {
      formRef.value.validateField(field.fieldName);
    }
  });
};

// 表单验证方法
const validateForm = async () => {
  try {
    if (formRef.value && formRef.value.validate) {
      await formRef.value.validate();
      return true;
    }
    return false;
  } catch (error) {
    console.error('表单验证失败:', error[0].message);
    showToast(error[0].message);
    return false;
  }
};

// -----------------------------------------------------
// 文件上传处理
// -----------------------------------------------------
const isPdf = (url) => url?.toLowerCase().endsWith(".pdf");
const getFileName = (url) => url.split("/").pop();

const previewFile = (url) => {
  // 在新窗口中打开文件预览
  window.open(url, '_blank');
};

const onFileChange = (field, event) => {
  const fname = field.fieldName;
  form.value[fname] = event.value;

  // 如果是文件URL，构建预览数据
  if (event.value && (event.value.includes('.pdf') || event.value.includes('.jpg') ||
    event.value.includes('.jpeg') || event.value.includes('.png'))) {
    form.value[fname + 'Value'] = [{ url: Host00 + event.value }];
  }

  clearFieldValidate(field);
};

// -----------------------------------------------------
// 提交
// -----------------------------------------------------
const submitForm = () => emit("submit", form);

// 暴露方法给父组件
defineExpose({
  formRef,
  validateForm
});

// 兼容微信小程序的规则设置
onMounted(() => {
  // 如果需要兼容微信小程序，并且校验规则中含有方法等，只能通过setRules方法设置规则。
  if (formRef.value && typeof formRef.value.setRules === 'function') {
    nextTick(() => {
      formRef.value.setRules(rules.value);
    });
  }
});
</script>

<style scoped lang="scss">
@import "@/uni.scss";

.u-form-item__body {
  padding: 0;
}

.form-group-title {
  font-weight: bold;
  margin: px2rpx(10) 0;
  display: flex;
  align-items: center;
}

.upload-wrapper {
  margin: px2rpx(10) 0;
}

.preview-img {
  width: px2rpx(130);
  border-radius: px2rpx(6);
  margin-top: px2rpx(6);
}

.pdf-link {
  display: inline-block;
  margin-top: px2rpx(6);
  color: #1989fa;
  text-decoration: underline;
}

.form-label1 {
  display: block;
  font-size: px2rpx(24);
  font-weight: 500;
  margin: px2rpx(24) 0;
  padding-left: px2rpx(12);
  position: relative;

  &::before {
    content: '';
    display: block;
    width: px2rpx(4);
    height: px2rpx(24);
    background-color: #ea002a;
    position: absolute;
    top: 0;
    left: 0;
  }
}
</style>