<template>
  <!-- 运营活动管理 - 新增/编辑页面（排版参考商家端 addActivity.vue） -->
  <div class="add-activity-container">
    <div class="header">
      <el-button @click="goBack"> 返回 </el-button>
      <h2 class="title">{{ type == "add" ? "新增" : "编辑" }}活动</h2>
    </div>

    <el-form ref="ruleFormRef" :model="activityModel" :rules="rules" class="form-box">
      <div class="form-content">
        <!-- 1. 活动类型 -->
        <div class="form-item-card">
          <div class="form-item card-item">
            <div class="form-label form-label-col">活动类型 <span class="required">*</span></div>
            <el-form-item prop="activityType" class="inline-form-item">
              <el-select v-model="activityModel.activityType" placeholder="请选择" clearable style="width: 100%">
                <el-option label="营销活动" value="MARKETING" />
                <el-option label="评价有礼" value="COMMENT" />
              </el-select>
            </el-form-item>
          </div>
        </div>

        <!-- 2. 活动宣传图（AI 辅助描述，与实际上传并存） -->
        <div class="form-item-card">
          <div class="form-item card-item">
            <div class="form-label form-label-col">活动宣传图 <span class="required">*</span></div>
            <div class="ai-promo-inner">
              <el-input
                v-model="activityModel.imgDescribe"
                type="textarea"
                placeholder="请描述你想举办的活动，AI助手会帮你自动生成活动banner与活动详情图~"
                maxlength="200"
                show-word-limit
                :autosize="{ minRows: 3 }"
                class="ai-promo-textarea"
              />
              <div class="ai-promo-footer">
                <span class="ai-char-count">{{ activityModel.imgDescribe.length }}/200</span>
                <el-button type="primary" size="small" :loading="aiGenerating" @click="handleAiGenerate"> AI 生成 </el-button>
              </div>
            </div>
          </div>
        </div>

        <!-- 3. 活动 banner（建议 2:1） -->
        <div class="form-item-card">
          <div class="form-item card-item">
            <div class="form-label form-label-col form-label-with-tip">
              <span>活动banner</span>
              <span class="required">*</span>
              <span class="form-label-tip">（建议2:1）</span>
            </div>
            <div class="upload-slot-dashed">
              <div class="upload-area upload-area-horizontal-21-9" :class="{ 'upload-full': titleFileList.length >= 1 }">
                <el-upload
                  v-model:file-list="titleFileList"
                  :accept="'.jpg,.jpeg,.png'"
                  :auto-upload="false"
                  :before-remove="handleBeforeRemove"
                  :disabled="hasUnuploadedImages"
                  :limit="1"
                  :on-change="handleTitleUploadChange"
                  :on-exceed="handleUploadExceed"
                  :on-preview="handlePictureCardPreview"
                  :on-remove="handleTitleRemove"
                  list-type="picture-card"
                >
                  <template #default>
                    <div v-if="titleFileList.length < 1" class="custom-upload-placeholder">
                      <el-icon class="upload-icon">
                        <Plus />
                      </el-icon>
                      <div class="upload-text">上传图片</div>
                      <div class="upload-text">({{ titleFileList.length }}/1)</div>
                    </div>
                  </template>
                </el-upload>
              </div>
            </div>
          </div>
        </div>

        <!-- 4. 活动详情图（仅营销活动需要） -->
        <div v-if="activityModel.activityType === 'MARKETING'" class="form-item-card">
          <div class="form-item card-item">
            <div class="form-label form-label-col">活动详情图 <span class="required">*</span></div>
            <div class="detail-upload-wrapper upload-slot-dashed">
              <div class="upload-area upload-area-vertical" :class="{ 'upload-full': detailFileList.length >= 9 }">
                <el-upload
                  v-model:file-list="detailFileList"
                  :accept="'.jpg,.jpeg,.png'"
                  :auto-upload="false"
                  :before-remove="handleBeforeRemove"
                  :disabled="hasUnuploadedImages"
                  :limit="9"
                  :on-change="handleDetailUploadChange"
                  :on-exceed="handleDetailUploadExceed"
                  :on-preview="handlePictureCardPreview"
                  :on-remove="handleDetailRemove"
                  list-type="picture-card"
                >
                  <template #default>
                    <div v-if="detailFileList.length < 9" class="custom-upload-placeholder custom-upload-placeholder-sm">
                      <el-icon class="upload-icon">
                        <Plus />
                      </el-icon>
                      <div class="upload-text">上传图片</div>
                      <div class="upload-text">({{ detailFileList.length }}/9)</div>
                    </div>
                  </template>
                </el-upload>
              </div>
            </div>
          </div>
        </div>

        <!-- 5. 活动名称 -->
        <div class="form-item-card">
          <div class="form-item card-item">
            <div class="form-label form-label-col">活动名称 <span class="required">*</span></div>
            <el-form-item prop="activityName" class="inline-form-item">
              <el-input
                v-model="activityModel.activityName"
                maxlength="30"
                placeholder="请输入活动名称"
                show-word-limit
                clearable
              />
            </el-form-item>
          </div>
        </div>

        <!-- 6. 营销活动：报名时间 → 活动时间 → 限制人数 → 活动详情 -->
        <template v-if="activityModel.activityType === 'MARKETING'">
          <div class="form-item-card">
            <div class="form-item card-item">
              <div class="form-label form-label-col form-label-dates">报名时间 <span class="required">*</span></div>
              <el-form-item prop="signupTimeRange" class="inline-form-item">
                <el-date-picker
                  v-model="activityModel.signupTimeRange"
                  :disabled-date="disabledSignupDate"
                  type="daterange"
                  range-separator="-"
                  start-placeholder="开始时间"
                  end-placeholder="结束时间"
                  value-format="YYYY-MM-DD"
                  format="YYYY/MM/DD"
                  class="form-date-picker"
                />
              </el-form-item>
            </div>
          </div>

          <div class="form-item-card">
            <div class="form-item card-item">
              <div class="form-label form-label-col form-label-dates">活动时间 <span class="required">*</span></div>
              <el-form-item prop="activityTimeRange" class="inline-form-item">
                <el-date-picker
                  v-model="activityModel.activityTimeRange"
                  :disabled-date="disabledDate"
                  type="daterange"
                  range-separator="-"
                  start-placeholder="开始时间"
                  end-placeholder="结束时间"
                  value-format="YYYY-MM-DD"
                  format="YYYY/MM/DD"
                  class="form-date-picker"
                />
              </el-form-item>
            </div>
          </div>

          <div class="form-item-card">
            <div class="form-item card-item form-item-valign-center">
              <div class="form-label form-label-col">活动限制人数 <span class="required">*</span></div>
              <el-form-item prop="activityLimitPeople" class="inline-form-item flex-row">
                <el-input
                  v-model="activityModel.activityLimitPeople"
                  placeholder="请输入活动参与人数，不填默认不限制"
                  maxlength="20"
                  @input="handlePositiveIntegerInput('activityLimitPeople', $event)"
                >
                  <template #suffix> 人 </template>
                </el-input>
              </el-form-item>
            </div>
          </div>

          <div class="form-item-card">
            <div class="form-item card-item">
              <div class="form-label form-label-col">活动详情 <span class="required">*</span></div>
              <el-form-item prop="activityDetails" class="inline-form-item">
                <el-input
                  v-model="activityModel.activityDetails"
                  type="textarea"
                  placeholder="请输入您的活动详情内容"
                  maxlength="300"
                  show-word-limit
                  :autosize="{ minRows: 4 }"
                />
              </el-form-item>
            </div>
          </div>
        </template>

        <!-- 7. 评价有礼：活动时间 → 参与次数 → 发放数量 → 券类型 + 优惠券内联 -->
        <template v-if="activityModel.activityType === 'COMMENT'">
          <div class="form-item-card">
            <div class="form-item card-item">
              <div class="form-label form-label-col form-label-dates">活动时间 <span class="required">*</span></div>
              <el-form-item prop="activityTimeRange" class="inline-form-item">
                <el-date-picker
                  v-model="activityModel.activityTimeRange"
                  :disabled-date="disabledDate"
                  type="daterange"
                  range-separator="-"
                  start-placeholder="开始时间"
                  end-placeholder="结束时间"
                  value-format="YYYY-MM-DD"
                  format="YYYY/MM/DD"
                  class="form-date-picker"
                />
              </el-form-item>
            </div>
          </div>

          <div class="form-item-card">
            <div class="form-item card-item form-item-valign-center">
              <div class="form-label form-label-col">用户可参与次数</div>
              <el-form-item prop="participationLimit" class="inline-form-item flex-row">
                <el-input
                  v-model="activityModel.participationLimit"
                  placeholder="请输入"
                  maxlength="20"
                  @input="handlePositiveIntegerInput('participationLimit', $event)"
                />
              </el-form-item>
            </div>
          </div>

          <div class="form-item-card">
            <div class="form-item card-item form-item-valign-center">
              <div class="form-label form-label-col">发放数量 <span class="required">*</span></div>
              <el-form-item
                :prop="activityModel.rewardType === 'VOUCHER' ? 'voucherQuantity' : 'couponQuantity'"
                class="inline-form-item flex-row"
              >
                <el-input
                  v-if="activityModel.rewardType === 'VOUCHER'"
                  v-model="activityModel.voucherQuantity"
                  placeholder="请输入发放数量"
                  maxlength="20"
                  @input="handlePositiveIntegerInput('voucherQuantity', $event)"
                />
                <el-input
                  v-else
                  v-model="activityModel.couponQuantity"
                  placeholder="请输入发放数量"
                  maxlength="20"
                  @input="handlePositiveIntegerInput('couponQuantity', $event)"
                />
              </el-form-item>
            </div>
          </div>

          <!-- 券类型 + 优惠券下拉选择 -->
          <div class="form-item-card">
            <div class="form-item card-item">
              <div class="form-label form-label-col">优惠券</div>
              <div class="form-item-main">
                <div class="form-row form-row-align coupon-type-header-row">
                  <div class="form-label-inline">券类型</div>
                  <div class="radio-group-wrapper coupon-type-row">
                    <div
                      class="radio-item"
                      :class="{ active: activityModel.rewardType === 'VOUCHER' }"
                      @click="setRewardType('VOUCHER')"
                    >
                      <div class="radio-circle">
                        <div v-if="activityModel.rewardType === 'VOUCHER'" class="radio-dot" />
                      </div>
                      <span class="radio-label">满减券</span>
                    </div>
                    <div
                      class="radio-item"
                      :class="{ active: activityModel.rewardType === 'COUPON' }"
                      @click="setRewardType('COUPON')"
                    >
                      <div class="radio-circle">
                        <div v-if="activityModel.rewardType === 'COUPON'" class="radio-dot" />
                      </div>
                      <span class="radio-label">折扣券</span>
                    </div>
                  </div>
                </div>

                <div class="coupon-select-block">
                  <div class="inline-coupon-label">
                    {{ activityModel.rewardType === "VOUCHER" ? "满减券" : "折扣券" }}
                    <span class="required">*</span>
                  </div>
                  <el-form-item
                    :prop="activityModel.rewardType === 'VOUCHER' ? 'voucherId' : 'couponId'"
                    class="inline-form-item"
                  >
                    <el-select
                      :model-value="activityModel.rewardType === 'VOUCHER' ? activityModel.voucherId : activityModel.couponId"
                      :placeholder="
                        couponLoading ? '加载中...' : '请选择' + (activityModel.rewardType === 'VOUCHER' ? '满减券' : '折扣券')
                      "
                      :loading="couponLoading"
                      clearable
                      filterable
                      style="width: 100%"
                      @update:model-value="val => selectCouponById(val)"
                    >
                      <el-option
                        v-for="(coupon, index) in couponList"
                        :key="(coupon.id ?? coupon.couponId ?? '') + '-' + index"
                        :label="getCouponOptionLabel(coupon)"
                        :value="coupon.id ?? coupon.couponId"
                      />
                    </el-select>
                  </el-form-item>
                </div>
              </div>
            </div>
          </div>
        </template>
      </div>

      <!-- 底部占位 + 提交按钮 -->
      <div class="bottom-placeholder" />
      <div class="bottom-button-area">
        <el-button type="primary" @click="handleSubmit"> 提交审核 </el-button>
        <el-button @click="goBack"> 取消 </el-button>
      </div>
    </el-form>

    <!-- 图片预览 -->
    <el-image-viewer
      v-if="imageViewerVisible"
      :initial-index="imageViewerInitialIndex"
      :url-list="imageViewerUrlList"
      @close="imageViewerVisible = false"
    />
  </div>
</template>

<script lang="tsx" name="newActivity" setup>
/**
 * 运营活动管理 - 新增/编辑页面
 * 功能：支持运营活动的新增和编辑操作
 */
import { computed, nextTick, onMounted, reactive, ref, watch } from "vue";
import type { FormInstance, UploadFile, UploadProps } from "element-plus";
import { ElMessage, ElMessageBox } from "element-plus";
import { Plus } from "@element-plus/icons-vue";
import { useRoute, useRouter } from "vue-router";
import {
  addActivity,
  getActivityDetail,
  getCouponList,
  generatePromotionImages,
  updateActivity
} from "@/api/modules/operationManagement";
import { uploadFileToOss } from "@/api/upload.js";
import { localGet } from "@/utils";

// ==================== 响应式数据定义 ====================

// 路由相关
const router = useRouter();
const route = useRoute();

// 页面状态
const type = ref<string>(""); // 页面类型：add-新增, edit-编辑
const id = ref<string>(""); // 页面ID参数

// 表单引用
const ruleFormRef = ref<FormInstance>();

// 优惠券列表
const couponList = ref<any[]>([]);
const couponLoading = ref(false);
const aiGenerating = ref(false);
/** 详情回填中：避免 rewardType 的 watch 把刚写入的券/发放数量清空 */
const detailHydrating = ref(false);

// 文件上传相关
const titleFileList = ref<UploadFile[]>([]);
const detailFileList = ref<UploadFile[]>([]);
const titleImageUrl = ref<string>("");
const detailImageUrl = ref<string>("");
const pendingUploadFiles = ref<UploadFile[]>([]);
const uploading = ref(false);
const imageViewerVisible = ref(false);
const imageViewerUrlList = ref<string[]>([]);
const imageViewerInitialIndex = ref(0);

// 是否有未上传的图片
const hasUnuploadedImages = computed(() => {
  const titlePending = titleFileList.value.some(file => file.status === "ready" || file.status === "uploading");
  const detailPending =
    activityModel.value.activityType === "MARKETING" &&
    detailFileList.value.some(file => file.status === "ready" || file.status === "uploading");
  return titlePending || detailPending;
});

// ==================== 表单验证规则 ====================
const rules = reactive({
  activityType: [{ required: true, message: "请选择活动类型", trigger: "change" }],
  activityName: [{ required: true, message: "请输入活动名称", trigger: "blur" }],
  activityTimeRange: [
    { required: true, message: "请选择活动时间", trigger: "change" },
    {
      validator: (rule: any, value: any, callback: any) => {
        if (!value || !Array.isArray(value) || value.length !== 2) {
          callback(new Error("请选择活动时间"));
          return;
        }
        const [startTime, endTime] = value;
        if (!startTime || !endTime) {
          callback(new Error("请选择完整的活动时间"));
          return;
        }
        const start = new Date(startTime);
        const end = new Date(endTime);
        const today = new Date();
        today.setHours(0, 0, 0, 0);
        // if (start < today) {
        //   callback(new Error("活动开始时间不能早于当前时间"));
        //   return;
        // }
        // if (start >= end) {
        //   callback(new Error("活动开始时间必须早于活动结束时间"));
        //   return;
        // }
        callback();
        // 活动时间验证通过后，重新验证报名时间（如果已设置）
        if (
          activityModel.value.activityType === "MARKETING" &&
          activityModel.value.signupTimeRange &&
          Array.isArray(activityModel.value.signupTimeRange) &&
          activityModel.value.signupTimeRange.length === 2
        ) {
          nextTick(() => {
            ruleFormRef.value?.validateField("signupTimeRange");
          });
        }
      },
      trigger: "change"
    }
  ],
  participationLimit: [
    { required: true, message: "请输入用户可参与次数", trigger: "blur" },
    {
      validator: (rule: any, value: any, callback: any) => {
        if (activityModel.value.activityType === "COMMENT") {
          if (!value) {
            callback(new Error("请输入用户可参与次数"));
            return;
          }
          const numValue = Number(value);
          if (isNaN(numValue) || !Number.isInteger(numValue) || numValue <= 0) {
            callback(new Error("用户可参与次数必须为正整数"));
            return;
          }
          if (numValue > 9999) {
            callback(new Error("用户可参与次数必须小于9999"));
            return;
          }
        }
        callback();
      },
      trigger: "blur"
    }
  ],
  rewardType: [{ required: true, message: "请选择券类型", trigger: "change" }],
  couponId: [
    {
      validator: (rule: any, value: any, callback: any) => {
        if (activityModel.value.activityType === "COMMENT" && activityModel.value.rewardType === "COUPON") {
          if (!value) {
            callback(new Error("请选择折扣券"));
            return;
          }
        }
        callback();
      },
      trigger: "change"
    }
  ],
  // 发放数量：提交时统一写入后端 couponQuantity
  couponQuantity: [
    {
      validator: (rule: any, value: any, callback: any) => {
        if (activityModel.value.activityType === "COMMENT" && activityModel.value.rewardType === "COUPON") {
          if (!value) {
            callback(new Error("请输入发放数量"));
            return;
          }
          const numValue = Number(value);
          if (isNaN(numValue) || !Number.isInteger(numValue) || numValue <= 0) {
            callback(new Error("发放数量必须为正整数"));
            return;
          }
          if (numValue > 99999) {
            callback(new Error("发放数量必须小于99999"));
            return;
          }
        }
        callback();
      },
      trigger: "blur"
    }
  ],
  voucherId: [
    {
      validator: (rule: any, value: any, callback: any) => {
        if (activityModel.value.activityType === "COMMENT" && activityModel.value.rewardType === "VOUCHER") {
          if (!value) {
            callback(new Error("请选择满减券"));
            return;
          }
        }
        callback();
      },
      trigger: "change"
    }
  ],
  voucherQuantity: [
    {
      validator: (rule: any, value: any, callback: any) => {
        if (activityModel.value.activityType === "COMMENT" && activityModel.value.rewardType === "VOUCHER") {
          if (!value) {
            callback(new Error("请输入发放数量"));
            return;
          }
          const numValue = Number(value);
          if (isNaN(numValue) || !Number.isInteger(numValue) || numValue <= 0) {
            callback(new Error("发放数量必须为正整数"));
            return;
          }
          if (numValue > 99999) {
            callback(new Error("发放数量必须小于99999"));
            return;
          }
        }
        callback();
      },
      trigger: "blur"
    }
  ],
  signupTimeRange: [
    { required: true, message: "请选择报名时间", trigger: "change" },
    {
      validator: (rule: any, value: any, callback: any) => {
        if (activityModel.value.activityType === "MARKETING") {
          if (!value || !Array.isArray(value) || value.length !== 2) {
            callback(new Error("请选择报名时间"));
            return;
          }
          const [startTime, endTime] = value;
          if (!startTime || !endTime) {
            callback(new Error("请选择完整的报名时间"));
            return;
          }
          const start = new Date(startTime);
          const end = new Date(endTime);
          start.setHours(0, 0, 0, 0);
          end.setHours(0, 0, 0, 0);

          // 获取当天日期
          const today = new Date();
          today.setHours(0, 0, 0, 0);

          // 1. 报名开始时间最早为当天
          if (start.getTime() < today.getTime()) {
            callback(new Error("报名开始时间不能早于当天"));
            return;
          }

          // 2. 报名开始时间必须早于报名结束时间
          if (start.getTime() >= end.getTime()) {
            callback(new Error("报名开始时间必须早于报名结束时间"));
            return;
          }

          // 3. 验证与活动时间的关系
          if (
            activityModel.value.activityTimeRange &&
            Array.isArray(activityModel.value.activityTimeRange) &&
            activityModel.value.activityTimeRange.length === 2
          ) {
            const activityEnd = new Date(activityModel.value.activityTimeRange[1]);
            activityEnd.setHours(0, 0, 0, 0);

            // 报名开始时间最晚要在活动结束时间之前
            if (start.getTime() >= activityEnd.getTime()) {
              callback(new Error("报名开始时间必须在活动结束时间之前"));
              return;
            }

            // 报名结束时间不能超过活动结束时间
            if (end.getTime() > activityEnd.getTime()) {
              callback(new Error("报名结束时间不能超过活动结束时间"));
              return;
            }
          }
        }
        callback();
      },
      trigger: "change"
    }
  ],
  activityDetails: [
    { required: true, message: "请输入活动详情", trigger: ["blur", "change"] },
    {
      validator: (rule: any, value: any, callback: any) => {
        if (activityModel.value.activityType === "MARKETING") {
          if (!value || value.trim() === "") {
            callback(new Error("请输入活动详情"));
            return;
          }
        }
        callback();
      },
      trigger: ["blur", "change"]
    }
  ],
  activityTitleImage: [
    {
      required: true,
      validator: (_rule: any, _value: any, callback: any) => {
        if (!titleImageUrl.value) {
          callback(new Error("请上传活动banner"));
          return;
        }
        callback();
      },
      trigger: ["change", "blur"]
    }
  ],
  activityDetailImage: [
    {
      required: true,
      validator: (_rule: any, _value: any, callback: any) => {
        if (activityModel.value.activityType !== "MARKETING") {
          callback();
          return;
        }
        const successFiles = detailFileList.value.filter((f: any) => f.status === "success" && f.url);
        if (successFiles.length === 0) {
          callback(new Error("请上传活动详情图"));
          return;
        }
        callback();
      },
      trigger: ["change", "blur"]
    }
  ]
});

// ==================== 活动信息数据模型 ====================
const activityModel = ref<any>({
  // 活动类型：'MARKETING'-营销活动，'COMMENT'-评论有礼
  activityType: "MARKETING",
  // 活动宣传图（包含标题和详情）
  promotionImages: null,
  // 活动标题图片
  activityTitleImg: null,
  // 活动详情图片
  activityDetailImg: null,
  // 活动标题图（用于表单验证）
  activityTitleImage: null,
  // 活动详情图（用于表单验证）
  activityDetailImage: null,
  // 活动名称
  activityName: "",
  // 活动时间范围
  activityTimeRange: [],
  // 用户可参与次数（评论有礼）
  participationLimit: "",
  // 券类型：'COUPON'-折扣券，'VOUCHER'-满减券（评论有礼）
  rewardType: "COUPON",
  /** 与后端一致：1-满减券 2-折扣券 */
  discountCouponType: 2,
  // 折扣券 ID（评论有礼）
  couponId: "",
  couponName: "",
  /** 折扣券路径下录入；提交时写入后端 couponQuantity（发放数量） */
  couponQuantity: "",
  voucherId: "",
  voucherName: "",
  /** 满减券路径下录入；提交时写入后端 couponQuantity（发放数量） */
  voucherQuantity: "",
  // 报名时间范围（营销活动）
  signupTimeRange: [],
  // 活动限制人数（营销活动）
  activityLimitPeople: "",
  // 活动详情（营销活动）
  activityDetails: "",
  // 上传图片方式：1-正常用户，2-使用描述
  uploadImgType: 1,
  // 图片描述（当uploadImgType为2时使用）
  imgDescribe: ""
});

// ==================== 日期选择器禁用规则 ====================

// 禁用日期（不能早于今天）
const disabledDate = (time: Date) => {
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  return time.getTime() < today.getTime();
};

// 禁用报名日期：报名开始时间最早为当天，报名结束时间不能超过活动结束时间
const disabledSignupDate = (time: Date) => {
  const t = new Date(time);
  t.setHours(0, 0, 0, 0);

  // 获取当天日期
  const today = new Date();
  today.setHours(0, 0, 0, 0);

  // 禁用早于当天的日期
  if (t.getTime() < today.getTime()) {
    return true;
  }

  // 未选择活动时间时，允许选择当天及之后的日期
  if (!activityModel.value.activityTimeRange || activityModel.value.activityTimeRange.length !== 2) {
    return false;
  }

  // 获取活动结束时间
  const activityEnd = new Date(activityModel.value.activityTimeRange[1]);
  activityEnd.setHours(0, 0, 0, 0);

  // 禁用超过活动结束时间的日期（报名结束时间不能超过活动结束时间）
  if (t.getTime() > activityEnd.getTime()) {
    return true;
  }

  return false;
};

// ==================== 图片参数转换函数 ====================

/**
 * 图片URL转换为upload组件的参数
 * @param imageUrl 图片URL
 * @returns UploadFile对象
 */
const handleImageParam = (imageUrl: string): UploadFile => {
  // 使用split方法以'/'为分隔符将URL拆分成数组
  const parts = imageUrl.split("/");
  // 取数组的最后一项，即图片名称
  const imageName = parts[parts.length - 1];
  return {
    uid: Date.now() + Math.random(),
    name: imageName,
    status: "success",
    percentage: 100,
    url: imageUrl
  } as unknown as UploadFile;
};

// ==================== 文件上传相关函数 ====================

/**
 * 检查文件是否在排队中（未上传）
 */
const isFilePending = (file: any): boolean => {
  if (file.status === "ready") {
    return true;
  }
  if (pendingUploadFiles.value.some(item => item.uid === file.uid)) {
    return true;
  }
  return false;
};

/**
 * 图片上传 - 删除前确认
 */
const handleBeforeRemove = async (uploadFile: any, uploadFiles: any[]): Promise<boolean> => {
  if (isFilePending(uploadFile)) {
    ElMessage.warning("图片尚未上传，请等待上传完成后再删除");
    return false;
  }
  try {
    await ElMessageBox.confirm("确定要删除这张图片吗？", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning"
    });
    return true;
  } catch {
    return false;
  }
};

/**
 * 活动标题图片上传 - 移除图片回调
 */
const handleTitleRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
  const file = uploadFile as any;
  const imageUrl = file.url;

  if (imageUrl) {
    titleImageUrl.value = "";
    activityModel.value.activityTitleImg = null;
    activityModel.value.activityTitleImage = null;
    // 触发表单验证
    nextTick(() => {
      ruleFormRef.value?.validateField("activityTitleImage");
    });
  }

  if (file.url && file.url.startsWith("blob:")) {
    URL.revokeObjectURL(file.url);
  }
  titleFileList.value = [...uploadFiles];
  ElMessage.success("图片已删除");
};

/**
 * 活动详情图片上传 - 移除图片回调
 */
const handleDetailRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
  const file = uploadFile as any;
  const imageUrl = file.url;

  // 更新图片URL列表（移除已删除的图片）
  const successFiles = uploadFiles.filter((f: any) => f.status === "success" && f.url);
  const imageUrls = successFiles.map((f: any) => f.url);
  detailImageUrl.value = imageUrls.length > 0 ? imageUrls.join(",") : "";
  activityModel.value.activityDetailImg = imageUrls.length > 0 ? { url: imageUrls.join(",") } : null;
  activityModel.value.activityDetailImage = imageUrls.length > 0 ? imageUrls.join(",") : "";

  // 触发表单验证
  nextTick(() => {
    ruleFormRef.value?.validateField("activityDetailImage");
  });

  if (file.url && file.url.startsWith("blob:")) {
    URL.revokeObjectURL(file.url);
  }
  detailFileList.value = [...uploadFiles];
  ElMessage.success("图片已删除");
};

/**
 * 上传文件超出限制提示（标题图）
 */
const handleUploadExceed: UploadProps["onExceed"] = () => {
  ElMessage.warning("最多只能上传1张图片");
};

/**
 * 活动详情图上传超出限制提示
 */
const handleDetailUploadExceed: UploadProps["onExceed"] = () => {
  ElMessage.warning("最多只能上传9张图片");
};

/**
 * 活动标题图片上传 - 文件变更
 */
const handleTitleUploadChange: UploadProps["onChange"] = async (uploadFile, uploadFiles) => {
  if (uploadFile.raw) {
    const fileType = uploadFile.raw.type.toLowerCase();
    const fileName = uploadFile.name.toLowerCase();
    const validTypes = ["image/jpeg", "image/jpg", "image/png"];
    const validExtensions = [".jpg", ".jpeg", ".png"];

    const isValidType = validTypes.includes(fileType) || validExtensions.some(ext => fileName.endsWith(ext));

    if (!isValidType) {
      // 从文件列表中移除不符合类型的文件
      const index = titleFileList.value.findIndex((f: any) => f.uid === uploadFile.uid);
      if (index > -1) {
        titleFileList.value.splice(index, 1);
      }
      // 从 uploadFiles 中移除
      const uploadIndex = uploadFiles.findIndex((f: any) => f.uid === uploadFile.uid);
      if (uploadIndex > -1) {
        uploadFiles.splice(uploadIndex, 1);
      }
      // 如果文件有 blob URL，释放它
      if (uploadFile.url && uploadFile.url.startsWith("blob:")) {
        URL.revokeObjectURL(uploadFile.url);
      }
      ElMessage.warning("只支持上传 JPG、JPEG 和 PNG 格式的图片");
      return;
    }

    // 检查文件大小，不得超过5M
    const maxSize = 5 * 1024 * 1024; // 5MB
    if (uploadFile.raw.size > maxSize) {
      // 从文件列表中移除超过大小的文件
      const index = titleFileList.value.findIndex((f: any) => f.uid === uploadFile.uid);
      if (index > -1) {
        titleFileList.value.splice(index, 1);
      }
      // 从 uploadFiles 中移除
      const uploadIndex = uploadFiles.findIndex((f: any) => f.uid === uploadFile.uid);
      if (uploadIndex > -1) {
        uploadFiles.splice(uploadIndex, 1);
      }
      // 如果文件有 blob URL，释放它
      if (uploadFile.url && uploadFile.url.startsWith("blob:")) {
        URL.revokeObjectURL(uploadFile.url);
      }
      ElMessage.warning("上传图片不得超过5M");
      return;
    }
  }

  const existingIndex = titleFileList.value.findIndex((f: any) => f.uid === uploadFile.uid);
  if (existingIndex === -1) {
    titleFileList.value.push(uploadFile);
  }

  const readyFiles = titleFileList.value.filter(file => file.status === "ready");
  if (readyFiles.length) {
    readyFiles.forEach(file => {
      if (!pendingUploadFiles.value.some(item => item.uid === file.uid)) {
        pendingUploadFiles.value.push(file);
      }
    });
  }
  processUploadQueue("title");
};

/**
 * 活动详情图片上传 - 文件变更
 */
const handleDetailUploadChange: UploadProps["onChange"] = async (uploadFile, uploadFiles) => {
  if (uploadFile.raw) {
    const fileType = uploadFile.raw.type.toLowerCase();
    const fileName = uploadFile.name.toLowerCase();
    const validTypes = ["image/jpeg", "image/jpg", "image/png"];
    const validExtensions = [".jpg", ".jpeg", ".png"];

    const isValidType = validTypes.includes(fileType) || validExtensions.some(ext => fileName.endsWith(ext));

    if (!isValidType) {
      // 从文件列表中移除不符合类型的文件
      const index = detailFileList.value.findIndex((f: any) => f.uid === uploadFile.uid);
      if (index > -1) {
        detailFileList.value.splice(index, 1);
      }
      // 从 uploadFiles 中移除
      const uploadIndex = uploadFiles.findIndex((f: any) => f.uid === uploadFile.uid);
      if (uploadIndex > -1) {
        uploadFiles.splice(uploadIndex, 1);
      }
      // 如果文件有 blob URL，释放它
      if (uploadFile.url && uploadFile.url.startsWith("blob:")) {
        URL.revokeObjectURL(uploadFile.url);
      }
      ElMessage.warning("只支持上传 JPG、JPEG 和 PNG 格式的图片");
      return;
    }

    // 检查文件大小，不得超过5M
    const maxSize = 5 * 1024 * 1024; // 5MB
    if (uploadFile.raw.size > maxSize) {
      // 从文件列表中移除超过大小的文件
      const index = detailFileList.value.findIndex((f: any) => f.uid === uploadFile.uid);
      if (index > -1) {
        detailFileList.value.splice(index, 1);
      }
      // 从 uploadFiles 中移除
      const uploadIndex = uploadFiles.findIndex((f: any) => f.uid === uploadFile.uid);
      if (uploadIndex > -1) {
        uploadFiles.splice(uploadIndex, 1);
      }
      // 如果文件有 blob URL，释放它
      if (uploadFile.url && uploadFile.url.startsWith("blob:")) {
        URL.revokeObjectURL(uploadFile.url);
      }
      ElMessage.warning("上传图片不得超过5M");
      return;
    }
  }

  const existingIndex = detailFileList.value.findIndex((f: any) => f.uid === uploadFile.uid);
  if (existingIndex === -1) {
    detailFileList.value.push(uploadFile);
  }

  const readyFiles = detailFileList.value.filter(file => file.status === "ready");
  if (readyFiles.length) {
    readyFiles.forEach(file => {
      if (!pendingUploadFiles.value.some(item => item.uid === file.uid)) {
        pendingUploadFiles.value.push(file);
      }
    });
  }
  processUploadQueue("detail");
};

/**
 * 处理上传队列 - 逐个上传文件
 */
const processUploadQueue = async (type: string) => {
  if (uploading.value || pendingUploadFiles.value.length === 0) {
    return;
  }
  const file = pendingUploadFiles.value.shift();
  if (file) {
    await uploadSingleFile(file, type);
    processUploadQueue(type);
  }
};

/**
 * 单文件上传图片
 */
const uploadSingleFile = async (file: UploadFile, uploadType: string) => {
  if (!file.raw) {
    return;
  }
  const rawFile = file.raw as File;
  file.status = "uploading";
  file.percentage = 0;
  uploading.value = true;

  try {
    const imageUrl = await uploadFileToOss(rawFile, "image");
    if (!imageUrl) {
      throw new Error("上传成功但未获取到图片URL");
    }

    file.status = "success";
    file.percentage = 100;
    file.url = imageUrl;
    file.response = { url: imageUrl };

    if (uploadType === "title") {
      titleImageUrl.value = imageUrl;
      activityModel.value.activityTitleImg = { url: imageUrl };
      activityModel.value.activityTitleImage = imageUrl;
      nextTick(() => {
        ruleFormRef.value?.validateField("activityTitleImage");
      });
    } else if (uploadType === "detail") {
      const successFiles = detailFileList.value.filter((f: any) => f.status === "success" && f.url);
      const imageUrls = successFiles.map((f: any) => f.url);
      detailImageUrl.value = imageUrls.length > 0 ? imageUrls.join(",") : "";
      activityModel.value.activityDetailImg = imageUrls.length > 0 ? { url: imageUrls.join(",") } : null;
      activityModel.value.activityDetailImage = imageUrls.length > 0 ? imageUrls.join(",") : "";
      nextTick(() => {
        ruleFormRef.value?.validateField("activityDetailImage");
      });
    }
  } catch (error: any) {
    // 上传失败时保持进度条为 0
    file.percentage = 0;
    // 不要设置 file.status = "fail"，直接移除文件，避免显示错误占位图
    if (file.url && file.url.startsWith("blob:")) {
      URL.revokeObjectURL(file.url);
    }
    // 从文件列表中移除失败的文件
    const index =
      uploadType === "title"
        ? titleFileList.value.findIndex((f: any) => f.uid === file.uid)
        : detailFileList.value.findIndex((f: any) => f.uid === file.uid);
    if (index > -1) {
      if (uploadType === "title") {
        titleFileList.value.splice(index, 1);
      } else {
        detailFileList.value.splice(index, 1);
      }
    }
    // Error message handled by global upload method, except for specific business logic errors
    if (error?.message && error.message.includes("未获取到图片URL")) {
      ElMessage.error(error.message);
    }
  } finally {
    uploading.value = false;
    // 触发视图更新
    if (uploadType === "title") {
      titleFileList.value = [...titleFileList.value];
    } else {
      detailFileList.value = [...detailFileList.value];
    }
  }
};

/**
 * 图片预览
 */
const handlePictureCardPreview = (file: any) => {
  if (isFilePending(file)) {
    ElMessage.warning("图片尚未上传，请等待上传完成后再预览");
    return;
  }
  if (file.status === "uploading" && file.url) {
    imageViewerUrlList.value = [file.url];
    imageViewerInitialIndex.value = 0;
    imageViewerVisible.value = true;
    return;
  }
  const allFiles = [...titleFileList.value, ...detailFileList.value];
  const urlList = allFiles
    .filter((item: any) => item.status === "success" && (item.url || item.response?.data))
    .map((item: any) => item.url || item.response?.data);
  const currentIndex = urlList.findIndex((url: string) => url === (file.url || file.response?.data));
  if (currentIndex < 0) {
    ElMessage.warning("图片尚未上传完成，无法预览");
    return;
  }
  imageViewerUrlList.value = urlList;
  imageViewerInitialIndex.value = currentIndex;
  imageViewerVisible.value = true;
};

// ==================== 加载优惠券列表函数 ====================

/**
 * 根据券类型加载优惠券/代金券列表
 */
const loadCouponList = async () => {
  if (activityModel.value.activityType !== "COMMENT") return;

  couponLoading.value = true;
  try {
    const params = {
      storeId: localGet("createdId"),
      tab: 0,
      size: 99,
      page: 1,
      couponName: "",
      couponsFromType: 1,
      couponType: activityModel.value.rewardType === "VOUCHER" ? 1 : 2 // 1 满减券 2 折扣券
    };
    const res: any = await getCouponList(params);
    if (res && res.code == 200) {
      const d = res.data || {};
      const raw = d.records ?? d.couponList ?? d.discountList?.records;
      couponList.value = Array.isArray(raw) ? raw : (raw?.records ?? raw?.list ?? []);
    }
  } catch (error) {
    console.error("加载优惠券列表失败:", error);
    couponList.value = [];
  } finally {
    couponLoading.value = false;
  }
};

/** 切换券类型：清空已选券并重新拉取列表 */
const setRewardType = (rewardType: "VOUCHER" | "COUPON") => {
  if (activityModel.value.rewardType === rewardType) return;
  activityModel.value.rewardType = rewardType;
  activityModel.value.discountCouponType = rewardType === "VOUCHER" ? 1 : 2;
  activityModel.value.couponId = "";
  activityModel.value.couponName = "";
  activityModel.value.couponQuantity = "";
  activityModel.value.voucherId = "";
  activityModel.value.voucherName = "";
  activityModel.value.voucherQuantity = "";
  couponList.value = [];
  loadCouponList();
};

/** 根据 ID 选择优惠券/满减券（下拉选择） */
const selectCouponById = (val: string | number) => {
  const id = val ?? "";
  const coupon = couponList.value.find((c: any) => (c.id ?? c.couponId) == id);
  const name = coupon ? (coupon.name ?? coupon.couponName) : "";
  if (activityModel.value.rewardType === "VOUCHER") {
    activityModel.value.voucherId = id;
    activityModel.value.voucherName = name;
  } else {
    activityModel.value.couponId = id;
    activityModel.value.couponName = name;
  }
};

/** 获取优惠券下拉选项显示文本 */
const getCouponOptionLabel = (coupon: any) => {
  const name = coupon.name ?? coupon.couponName ?? "";
  const isDiscount = coupon.couponType === 2 || (coupon.discountRate != null && coupon.discountRate !== "");
  let suffix = "";
  if (isDiscount) {
    suffix = !coupon.minimumSpendingAmount
      ? `（${coupon.discountRate}折 无门槛）`
      : `（${coupon.discountRate}折 满${coupon.minimumSpendingAmount}可用）`;
  } else {
    suffix = !coupon.minimumSpendingAmount
      ? `（${coupon.nominalValue ?? 0}元 无门槛）`
      : `（${coupon.nominalValue ?? 0}元 满${coupon.minimumSpendingAmount}可用）`;
  }
  return name + suffix;
};

/** 日期格式化（- -> /） */
const handlegetTime = (val: string) => {
  if (val && typeof val === "string" && val.includes("-")) {
    return val.split("-").join("/");
  }
  return val || "";
};

/** 将 AI 接口返回写入 banner / 详情图（评价有礼仅写入 banner） */
const applyPromotionImagesFromResponse = (data: any) => {
  if (!data || typeof data !== "object") return;
  const isMarketing = activityModel.value.activityType === "MARKETING";

  const titleObj = data.activityTitleImg;
  if (titleObj && titleObj.imgUrl) {
    const url = titleObj.imgUrl;
    titleImageUrl.value = url;
    activityModel.value.activityTitleImage = url;
    titleFileList.value = [handleImageParam(url)];
  } else {
    const banner =
      data.bannerUrl ||
      data.titleImgUrl ||
      data.activityTitleImgUrl ||
      data.titleImageUrl ||
      (typeof data.activityTitleImage === "string" ? data.activityTitleImage : null);
    if (banner) {
      const url = typeof banner === "string" ? banner : banner?.url || banner;
      if (url) {
        titleImageUrl.value = url;
        activityModel.value.activityTitleImage = url;
        titleFileList.value = [handleImageParam(url)];
      }
    }
  }

  if (!isMarketing) {
    nextTick(() => {
      ruleFormRef.value?.validateField(["activityTitleImage"]);
    });
    return;
  }

  const detailObj = data.activityDetailImg;
  if (detailObj) {
    let urls: string[] = [];
    if (typeof detailObj === "string") {
      urls = detailObj
        .split(",")
        .map((s: string) => s.trim())
        .filter(Boolean);
    } else if (detailObj.imgUrl) {
      urls = [detailObj.imgUrl];
    } else if (Array.isArray(detailObj)) {
      urls = detailObj.map((item: any) => (typeof item === "string" ? item : item?.imgUrl || item?.url)).filter(Boolean);
    }
    if (urls.length) {
      detailImageUrl.value = urls.join(",");
      activityModel.value.activityDetailImage = urls.join(",");
      detailFileList.value = urls.map((url: string) => handleImageParam(url));
    }
  } else {
    const detailRaw = data.detailImgUrls || data.detailUrls || data.activityDetailImgUrl || data.detailImageUrls;
    if (detailRaw != null && detailRaw !== "") {
      const arr = Array.isArray(detailRaw)
        ? detailRaw
        : String(detailRaw)
            .split(",")
            .map((s: string) => s.trim())
            .filter(Boolean);
      const urls = arr.map((item: any) => (typeof item === "string" ? item : item?.url || item?.imgUrl || item)).filter(Boolean);
      if (urls.length) {
        detailImageUrl.value = urls.join(",");
        activityModel.value.activityDetailImage = urls.join(",");
        detailFileList.value = urls.map((url: string) => handleImageParam(url));
      }
    }
  }
};

/** AI 生成活动宣传图 */
const handleAiGenerate = async () => {
  const desc = activityModel.value.imgDescribe?.trim();
  if (!desc) {
    ElMessage.warning("请先填写活动宣传描述");
    return;
  }
  if (aiGenerating.value) return;
  aiGenerating.value = true;
  try {
    const res: any = await generatePromotionImages({ activityName: desc, uploadImgType: 2 });
    if (res && res.code == 200) {
      applyPromotionImagesFromResponse(res.data);
      nextTick(() => {
        const fields: string[] =
          activityModel.value.activityType === "MARKETING"
            ? ["activityTitleImage", "activityDetailImage"]
            : ["activityTitleImage"];
        ruleFormRef.value?.validateField(fields);
      });
      ElMessage.success(res.msg || "图片生成成功");
    } else {
      ElMessage.error(res?.msg || "生成失败");
    }
  } catch (error: any) {
    console.error("generatePromotionImages:", error);
    ElMessage.error(error?.message || "生成失败，请重试");
  } finally {
    aiGenerating.value = false;
  }
};

// ==================== 监听器 ====================

/**
 * 监听活动类型变化，切换时清除相关数据并重新验证
 */
watch(
  () => activityModel.value.activityType,
  (newVal, oldVal) => {
    // 如果 oldVal 为空或 undefined，说明是初始化，不处理
    if (oldVal === undefined || oldVal === null || oldVal === "") return;
    // 如果新旧值相同，不处理
    if (newVal === oldVal) return;

    nextTick(() => {
      // 兼容旧数据：如果传入的是数字，转换为字符串
      let typeValue = newVal;
      if (typeValue == 1 || typeValue == "1") {
        typeValue = "MARKETING";
      } else if (typeValue == 2 || typeValue == "2") {
        typeValue = "COMMENT";
      }

      if (typeValue === "MARKETING") {
        // 切换到营销活动：清除评论有礼相关字段
        activityModel.value.participationLimit = "";
        activityModel.value.rewardType = "COUPON";
        activityModel.value.discountCouponType = 2;
        activityModel.value.couponId = "";
        activityModel.value.couponName = "";
        activityModel.value.couponQuantity = "";
        activityModel.value.voucherId = "";
        activityModel.value.voucherName = "";
        activityModel.value.voucherQuantity = "";
        couponList.value = [];
        // 清除评论有礼字段的验证状态
        ruleFormRef.value?.clearValidate([
          "participationLimit",
          "rewardType",
          "couponId",
          "couponQuantity",
          "voucherId",
          "voucherQuantity"
        ]);
      } else if (typeValue === "COMMENT") {
        // 切换到评论有礼：清除营销活动相关字段（含活动详情图，评价有礼不需要）
        activityModel.value.signupTimeRange = [];
        activityModel.value.activityLimitPeople = "";
        activityModel.value.activityDetails = "";
        const detailUids = new Set(detailFileList.value.map((f: any) => f.uid));
        detailFileList.value.forEach((f: any) => {
          if (f?.url && String(f.url).startsWith("blob:")) URL.revokeObjectURL(f.url);
        });
        detailFileList.value = [];
        detailImageUrl.value = "";
        activityModel.value.activityDetailImg = null;
        activityModel.value.activityDetailImage = "";
        pendingUploadFiles.value = pendingUploadFiles.value.filter((f: any) => !detailUids.has(f.uid));
        activityModel.value.discountCouponType = activityModel.value.rewardType === "VOUCHER" ? 1 : 2;
        // 清除营销活动字段的验证状态
        ruleFormRef.value?.clearValidate(["signupTimeRange", "activityLimitPeople", "activityDetails", "activityDetailImage"]);
        // 加载优惠券列表
        loadCouponList();
      }
    });
  },
  { immediate: false }
);

/**
 * 监听券类型变化，切换时重新加载列表并清空已选券
 */
watch(
  () => activityModel.value.rewardType,
  (newVal, oldVal) => {
    if (detailHydrating.value) return;
    if (oldVal === undefined) return; // 初始化时不处理
    if (newVal === oldVal) return;
    if (activityModel.value.activityType !== "COMMENT") return; // 只有评论有礼才处理

    nextTick(() => {
      activityModel.value.discountCouponType = newVal === "VOUCHER" ? 1 : 2;
      // 清空已选券（根据类型清空对应字段）
      if (newVal === "VOUCHER") {
        activityModel.value.voucherId = "";
        activityModel.value.voucherName = "";
        activityModel.value.voucherQuantity = "";
        ruleFormRef.value?.clearValidate(["voucherId", "voucherQuantity"]);
      } else {
        activityModel.value.couponId = "";
        activityModel.value.couponName = "";
        activityModel.value.couponQuantity = "";
        ruleFormRef.value?.clearValidate(["couponId", "couponQuantity"]);
      }
      couponList.value = [];
      // 重新加载列表
      loadCouponList();
    });
  }
);

/**
 * 监听活动时间变化，如果报名时间不在新的活动时间范围内则清空并提示
 */
watch(
  () => activityModel.value.activityTimeRange,
  (newVal, oldVal) => {
    // 初始化时不处理
    if (oldVal === undefined || oldVal === null) return;

    // 只有营销活动才需要检查报名时间
    if (activityModel.value.activityType !== "MARKETING") return;

    // 如果活动时间已选择且报名时间已选择
    if (
      newVal &&
      newVal.length === 2 &&
      activityModel.value.signupTimeRange &&
      activityModel.value.signupTimeRange.length === 2
    ) {
      const activityStart = new Date(newVal[0]);
      activityStart.setHours(0, 0, 0, 0);
      const activityEnd = new Date(newVal[1]);
      activityEnd.setHours(0, 0, 0, 0);
      const signupStart = new Date(activityModel.value.signupTimeRange[0]);
      signupStart.setHours(0, 0, 0, 0);
      const signupEnd = new Date(activityModel.value.signupTimeRange[1]);
      signupEnd.setHours(0, 0, 0, 0);

      // 检查报名时间是否符合新的规则：
      // 1. 报名开始时间 >= 当天
      // 2. 报名开始时间 < 活动结束时间
      // 3. 报名结束时间 <= 活动结束时间
      const today = new Date();
      today.setHours(0, 0, 0, 0);

      const outOfRange =
        signupStart.getTime() < today.getTime() || // 报名开始时间早于当天
        signupStart.getTime() >= activityEnd.getTime() || // 报名开始时间 >= 活动结束时间
        signupEnd.getTime() > activityEnd.getTime(); // 报名结束时间 > 活动结束时间

      if (outOfRange) {
        activityModel.value.signupTimeRange = [];
        nextTick(() => {
          ruleFormRef.value?.clearValidate("signupTimeRange");
          ElMessage.warning("活动时间已调整，报名时间不符合规则，请重新选择报名时间");
        });
      } else {
        nextTick(() => {
          ruleFormRef.value?.validateField("signupTimeRange");
        });
      }
    }
  }
);

// ==================== 生命周期钩子 ====================

/**
 * 组件挂载时初始化
 */
onMounted(async () => {
  id.value = (route.query.id as string) || "";
  type.value = (route.query.type as string) || "";

  // 支持从路由获取活动类型（与商家端一致）
  const routeType = route.query.activityType as string;
  if (routeType) {
    if (routeType == "1" || routeType == "MARKETING") activityModel.value.activityType = "MARKETING";
    else if (routeType == "2" || routeType == "COMMENT") activityModel.value.activityType = "COMMENT";
  }

  // 如果是评论有礼类型，初始化时加载优惠券列表
  if (activityModel.value.activityType === "COMMENT") {
    await loadCouponList();
  }

  // 编辑模式下加载数据
  if (type.value != "add" && id.value) {
    try {
      const res: any = await getActivityDetail({ id: id.value });
      if (res && res.code == 200) {
        // 兼容旧数据：如果后端返回的是数字，转换为字符串
        if (res.data.activityType !== undefined) {
          let activityTypeValue = res.data.activityType;
          if (activityTypeValue == 1 || activityTypeValue == "1") {
            activityTypeValue = "MARKETING";
          } else if (activityTypeValue == 2 || activityTypeValue == "2") {
            activityTypeValue = "COMMENT";
          }
          activityModel.value.activityType = activityTypeValue;
        }

        // 合并其他数据
        activityModel.value.activityName = res.data.activityName || "";

        // 处理活动时间范围
        if (res.data.startTime && res.data.endTime) {
          // 只取日期部分（去掉时分秒）
          const startDate = res.data.startTime.split(" ")[0];
          const endDate = res.data.endTime.split(" ")[0];
          activityModel.value.activityTimeRange = [startDate, endDate];
        }

        // 根据活动类型加载对应字段
        if (activityModel.value.activityType === "MARKETING") {
          // 营销活动：加载报名时间、活动限制人数、活动详情
          if (res.data.signupStartTime && res.data.signupEndTime) {
            // 只取日期部分（去掉时分秒）
            const signupStartDate = res.data.signupStartTime.split(" ")[0];
            const signupEndDate = res.data.signupEndTime.split(" ")[0];
            activityModel.value.signupTimeRange = [signupStartDate, signupEndDate];
          } else {
            activityModel.value.signupTimeRange = [];
          }
          // 加载活动限制人数
          if (res.data.activityLimitPeople !== undefined && res.data.activityLimitPeople !== null) {
            activityModel.value.activityLimitPeople = String(res.data.activityLimitPeople);
          } else {
            activityModel.value.activityLimitPeople = "";
          }
          // 加载活动详情
          activityModel.value.activityDetails = res.data.activityDetails || "";
        } else if (activityModel.value.activityType === "COMMENT") {
          detailHydrating.value = true;
          try {
            // 评论有礼：discountCouponType 1=满减券 2=折扣券（优先于 rewardType / couponType）
            const dct = res.data.discountCouponType;
            if (dct !== undefined && dct !== null && dct !== "") {
              const n = Number(dct);
              activityModel.value.discountCouponType = n === 1 ? 1 : 2;
              activityModel.value.rewardType = n === 1 ? "VOUCHER" : "COUPON";
            } else if (res.data.rewardType === "VOUCHER" || res.data.rewardType === "COUPON") {
              activityModel.value.rewardType = res.data.rewardType;
              activityModel.value.discountCouponType = res.data.rewardType === "VOUCHER" ? 1 : 2;
            } else if (res.data.couponType !== undefined && res.data.couponType !== null) {
              // 兼容：couponType 4 -> 满减，其它 -> 折扣
              activityModel.value.rewardType = Number(res.data.couponType) === 4 ? "VOUCHER" : "COUPON";
              activityModel.value.discountCouponType = activityModel.value.rewardType === "VOUCHER" ? 1 : 2;
            } else {
              activityModel.value.rewardType = "COUPON";
              activityModel.value.discountCouponType = 2;
            }
            // 后端 couponQuantity 为发放数量；可能统一返回 couponId / couponQuantity，按券类型写入 voucher* 或 coupon*
            const unifiedId = res.data.couponId ?? res.data.voucherId ?? "";
            const unifiedName = res.data.couponName ?? res.data.voucherName ?? "";
            const unifiedQty = res.data.couponQuantity ?? res.data.voucherQuantity;
            if (activityModel.value.rewardType === "VOUCHER") {
              activityModel.value.voucherId = unifiedId;
              activityModel.value.voucherName = unifiedName;
              activityModel.value.voucherQuantity = unifiedQty !== undefined && unifiedQty !== null ? String(unifiedQty) : "";
              activityModel.value.couponId = "";
              activityModel.value.couponName = "";
              activityModel.value.couponQuantity = "";
            } else {
              activityModel.value.couponId = unifiedId;
              activityModel.value.couponName = unifiedName;
              activityModel.value.couponQuantity = unifiedQty !== undefined && unifiedQty !== null ? String(unifiedQty) : "";
              activityModel.value.voucherId = "";
              activityModel.value.voucherName = "";
              activityModel.value.voucherQuantity = "";
            }
            // 加载用户可参与次数
            if (res.data.participationLimit !== undefined && res.data.participationLimit !== null) {
              activityModel.value.participationLimit = String(res.data.participationLimit);
            } else {
              activityModel.value.participationLimit = "";
            }
            // 根据券类型加载对应的列表
            await loadCouponList();
          } finally {
            await nextTick();
            detailHydrating.value = false;
          }
        }
        // 加载图片描述
        if (res.data.imgDescribe) {
          activityModel.value.imgDescribe = res.data.imgDescribe;
        } else {
          activityModel.value.imgDescribe = "";
        }
        // 编辑模式：始终加载图片数据（无论原始uploadImgType是什么）
        // 如果有标题图片，添加到文件列表
        if (res.data.activityTitleImgUrl) {
          const titleImgUrl = res.data.activityTitleImgUrl;
          if (titleImgUrl) {
            titleImageUrl.value = titleImgUrl;
            activityModel.value.activityTitleImg = res.data.activityTitleImgUrl;
            activityModel.value.activityTitleImage = titleImgUrl;
            const titleFile = handleImageParam(titleImgUrl);
            titleFileList.value = [titleFile];
          }
        }
        // 营销活动：加载详情图（评价有礼不需要）
        if (activityModel.value.activityType === "MARKETING" && res.data.activityDetailImgUrl) {
          let detailImgUrls: string[] = [];
          if (typeof res.data.activityDetailImgUrl === "string") {
            detailImgUrls = res.data.activityDetailImgUrl.split(",").filter((url: string) => url.trim());
          } else if (Array.isArray(res.data.activityDetailImgUrl)) {
            detailImgUrls = res.data.activityDetailImgUrl.filter((url: any) => url);
          }

          if (detailImgUrls.length > 0) {
            detailImageUrl.value = detailImgUrls.join(",");
            activityModel.value.activityDetailImg = res.data.activityDetailImgUrl;
            activityModel.value.activityDetailImage = detailImgUrls.join(",");
            detailFileList.value = detailImgUrls.map((url: string) => handleImageParam(url));
          }
        } else if (activityModel.value.activityType === "COMMENT") {
          detailFileList.value = [];
          detailImageUrl.value = "";
          activityModel.value.activityDetailImg = null;
          activityModel.value.activityDetailImage = "";
        }
      }
    } catch (error) {
      console.error("加载活动详情失败:", error);
      ElMessage.error("加载活动详情失败");
    }
  }
  await nextTick();
  ruleFormRef.value?.clearValidate();
});

// ==================== 事件处理函数 ====================

/**
 * 处理正整数输入（只允许输入正整数）
 */
const handlePositiveIntegerInput = (field: string, ev: any) => {
  let val = "";
  if (typeof ev === "string") val = ev;
  else if (ev?.target?.value !== undefined) val = ev.target.value;
  else val = String(activityModel.value[field] ?? "");

  const filteredValue = val.replace(/[^\d]/g, "").slice(0, 20);
  if (field === "activityLimitPeople") activityModel.value.activityLimitPeople = filteredValue;
  else if (field === "participationLimit") activityModel.value.participationLimit = filteredValue;
  else if (field === "voucherQuantity") activityModel.value.voucherQuantity = filteredValue;
  else if (field === "couponQuantity") activityModel.value.couponQuantity = filteredValue;
};

/**
 * 返回上一页
 */
const goBack = () => {
  router.go(-1);
};

/**
 * 提交表单
 */
const handleSubmit = async () => {
  if (!ruleFormRef.value) return;

  // 若有未上传的图片，阻止提交
  if (hasUnuploadedImages.value) {
    ElMessage.warning("请等待图片上传完成后再提交");
    return;
  }

  await ruleFormRef.value.validate(async valid => {
    if (valid) {
      const [activityStartDate, activityEndDate] = activityModel.value.activityTimeRange || [];
      // 活动时间：开始日期传当天 00:00:00，结束日期传当天 23:59:59
      const startTime = activityStartDate ? `${activityStartDate} 00:00:00` : "";
      const endTime = activityEndDate ? `${activityEndDate} 23:59:59` : "";
      const detailUrls =
        activityModel.value.activityType === "MARKETING" && detailImageUrl.value
          ? detailImageUrl.value
              .split(",")
              .map((s: string) => s.trim())
              .filter(Boolean)
          : [];
      const auditParam = {
        text: activityModel.value.imgDescribe?.trim()
          ? `${activityModel.value.activityName}，${activityModel.value.imgDescribe.trim()}`
          : activityModel.value.activityName,
        image_urls: [titleImageUrl.value, ...detailUrls].filter(Boolean)
      };
      const params: any = {
        activityType: activityModel.value.activityType,
        activityName: activityModel.value.activityName,
        startTime,
        endTime,
        uploadImgType: 1, // 固定本地上传
        storeId: localGet("createdId"),
        groupType: localGet("businessSection"),
        status: 1, // 1-待审核
        auditParam: JSON.stringify(auditParam)
      };

      // 根据活动类型添加不同的字段
      if (activityModel.value.activityType === "MARKETING") {
        const [signupStartDate, signupEndDate] = activityModel.value.signupTimeRange || [];
        params.signupStartTime = signupStartDate ? `${signupStartDate} 00:00:00` : "";
        params.signupEndTime = signupEndDate ? `${signupEndDate} 23:59:59` : "";
        params.activityLimitPeople = activityModel.value.activityLimitPeople;
        params.activityDetails = activityModel.value.activityDetails;
      } else if (activityModel.value.activityType === "COMMENT") {
        // 评价有礼：discountCouponType 1=满减券 2=折扣券；couponQuantity=发放数量（满减/折扣均走此字段）
        params.participationLimit = activityModel.value.participationLimit;
        params.rewardType = "COUPON";
        params.discountCouponType = activityModel.value.rewardType === "VOUCHER" ? 1 : 2;
        activityModel.value.discountCouponType = params.discountCouponType;
        const selectedId =
          activityModel.value.rewardType === "VOUCHER" ? activityModel.value.voucherId : activityModel.value.couponId;
        const selectedQuantity =
          activityModel.value.rewardType === "VOUCHER" ? activityModel.value.voucherQuantity : activityModel.value.couponQuantity;
        params.couponId = selectedId;
        params.couponQuantity = selectedQuantity; // 发放数量
      }

      // 图片参数
      params.activityTitleImg = {
        imgUrl: titleImageUrl.value,
        imgSort: 0,
        storeId: localGet("createdId")
      };
      params.activityDetailImg = {
        imgUrl: activityModel.value.activityType === "MARKETING" ? detailImageUrl.value : "",
        imgSort: 0,
        storeId: localGet("createdId")
      };
      if (activityModel.value.imgDescribe?.trim()) {
        params.imgDescribe = activityModel.value.imgDescribe.trim();
      }

      try {
        let res: any;
        if (type.value == "add") {
          res = await addActivity(params);
        } else {
          params.id = id.value;
          res = await updateActivity(params);
        }

        if (res && res.code == 200) {
          ElMessage.success(type.value == "add" ? "新增成功" : "编辑成功");
          goBack();
        } else {
          ElMessage.error(res?.msg || "操作失败");
        }
      } catch (error) {
        console.error("提交失败:", error);
        ElMessage.error("操作失败");
      }
    }
  });
};
</script>

<style lang="scss" scoped>
.add-activity-container {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  background: #f5f7fa;
}
.header {
  display: flex;
  align-items: center;
  padding: 16px 24px;
  background: #ffffff;
  border-bottom: 1px solid #e4e7ed;
  .title {
    flex: 1;
    margin: 0;
    font-size: 18px;
    font-weight: 600;
    color: #303133;
    text-align: center;
  }
}
.form-box {
  display: flex;
  flex: 1;
  flex-direction: column;
  background: #ffffff;
}
.form-content {
  box-sizing: border-box;
  flex: 1;
  width: 100%;
  max-width: 700px;
  padding-bottom: 24px;
  margin: 24px 24px 0;
  margin-right: auto;
}
.form-item-card {
  margin-bottom: 20px;
}
.form-item {
  width: 100%;
  max-width: 100%;
  padding: 16px 0;
  margin: 0;
  background: #ffffff;
  border-radius: 0;
  box-shadow: none;
  &.card-item,
  &.form-row-item {
    display: flex;
    flex-direction: row;
    gap: 16px 24px;
    align-items: flex-start;
  }
  &.form-item-valign-center {
    align-items: center;
    .form-label-col {
      padding-top: 0;
    }
  }
}
.form-label-col {
  flex: 0 0 140px;
  width: 140px;
  padding-top: 6px;
  margin-bottom: 0 !important;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.4;
  color: #303133;
  text-align: left;
}
.form-label-inline {
  flex-shrink: 0;
  margin-right: 16px;
  font-size: 14px;
  font-weight: 500;
  color: #303133;
}
.form-item-main {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
}
.form-label {
  margin-bottom: 12px;
  font-size: 14px;
  font-weight: 500;
  color: #1a1a1a;
  &.form-label-plain {
    margin-bottom: 12px;
  }
  &.form-label-dates {
    margin-bottom: 12px;
  }
  &.form-label-with-tip {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    align-items: baseline;
    margin-bottom: 0 !important;
  }
}
.form-label-tip {
  margin-left: 4px;
  font-size: 12px;
  color: #9ca3af;
}
.required {
  margin-left: 2px;
  color: #ff4d4f;
}
.ai-promo-inner {
  padding: 16px;
  background: #fafbfd;
  border: 1px dashed #cfd6e0;
  border-radius: 8px;
}
.ai-promo-textarea {
  :deep(textarea) {
    font-size: 14px;
    line-height: 1.5;
  }
}
.ai-promo-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 12px;
}
.ai-char-count {
  font-size: 12px;
  color: #9ca3af;
}
.upload-slot-dashed {
  margin-top: 8px;
}
.detail-upload-wrapper {
  margin-top: 8px;
}
.inline-form-item {
  flex: 1;
  width: 100%;
  min-width: 0;
  margin-bottom: 0 !important;
  :deep(.el-form-item__content) {
    flex-wrap: wrap;
    margin-left: 0 !important;
  }
  &.flex-row {
    display: flex;
    gap: 8px;
    align-items: center;
    :deep(.el-input) {
      flex: 1;
    }
  }
}
.form-item.card-item > .inline-form-item,
.form-item.card-item > .ai-promo-inner,
.form-item.card-item > .upload-slot-dashed,
.form-item.card-item > .detail-upload-wrapper {
  flex: 1;
  min-width: 0;
}
.unit-suffix {
  flex-shrink: 0;
  font-size: 14px;
  color: #606266;
}
.char-count-below-input,
.char-count-detail {
  margin-top: 8px;
  font-size: 12px;
  color: #9ca3af;
}
.form-date-picker {
  width: 100%;
}
.form-row-align {
  display: flex;
  align-items: center;
}
.coupon-type-header-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 0;
}
.radio-group-wrapper {
  display: flex;
  gap: 24px;
  &.coupon-type-row {
    flex: 1;
    justify-content: flex-start;
    margin-top: 0;
  }
  .radio-item {
    display: flex;
    gap: 8px;
    align-items: center;
    cursor: pointer;
    .radio-circle {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 16px;
      height: 16px;
      border: 2px solid #cccccc;
      border-radius: 50%;
      .radio-dot {
        width: 8px;
        height: 8px;
        background: #409eff;
        border-radius: 50%;
      }
    }
    &.active .radio-circle {
      border-color: #409eff;
    }
    .radio-label {
      font-size: 14px;
      color: #334154;
    }
  }
}
.coupon-select-block,
.inline-coupon-block {
  margin-top: 0;
}
.inline-coupon-label {
  margin-bottom: 12px;
  font-size: 14px;
  font-weight: 500;
  .required {
    color: #ff4d4f;
  }
}
.inline-coupon-scroll {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-height: 280px;
  overflow-y: auto;
}
.inline-coupon-card-wrap {
  cursor: pointer;
}
.coupon-detail-item {
  display: flex;
  align-items: center;
  padding: 12px 16px;
  background: #ffffff;
  border: 1px solid #e4e7ed;
  border-radius: 8px;
  transition: all 0.2s;
  &.inline-item-selected {
    background: #ecf5ff;
    border-color: #409eff;
  }
  .leftitem {
    flex-shrink: 0;
    padding-right: 16px;
    font-size: 18px;
    font-weight: 600;
    color: #e6a23c;
    text-align: center;
  }
  .leftitem-discount .discount-value {
    display: flex;
    align-items: baseline;
  }
  .discount-num {
    font-size: 24px;
  }
  .discount-unit {
    margin-left: 2px;
    font-size: 12px;
  }
  .discount-threshold {
    margin-top: 4px;
    font-size: 12px;
    color: #909399;
  }
  .rightItem {
    display: flex;
    flex: 1;
    align-items: center;
    justify-content: space-between;
  }
  .rightItem-text .coupon-description {
    font-size: 14px;
    color: #303133;
  }
  .coupon-time {
    margin-top: 4px;
    font-size: 12px;
    color: #909399;
  }
  .picker-checkbox {
    display: flex;
    flex-shrink: 0;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border: 1px solid #dcdfe6;
    border-radius: 50%;
    &.checked {
      color: #ffffff;
      background: #409eff;
      border-color: #409eff;
    }
  }
}
.inline-coupon-empty {
  padding: 24px;
  font-size: 14px;
  color: #909399;
  text-align: center;
}
.custom-upload-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  min-height: 120px;
  font-size: 14px;
  color: #8c939d;
  background: #fafafa;
  border: 1px dashed #dcdfe6;
  border-radius: 8px;
  &.custom-upload-placeholder-sm {
    min-height: 100px;
  }
  .upload-icon {
    margin-bottom: 8px;
    font-size: 28px;
  }
  .upload-text {
    font-size: 12px;
  }
}
.bottom-placeholder {
  height: 8px;
}
.bottom-button-area {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: flex-start;
  max-width: 960px;
  padding: 16px 0 32px;
  margin: 0 24px 24px;
  margin-right: auto;
  background: transparent;
  border-top: none;
}
.upload-area {
  width: 100%;
  :deep(.el-upload--picture-card) {
    width: 100%;
    height: 180px;
  }
  :deep(.el-upload-list--picture-card) {
    width: 100%;
    .el-upload-list__item {
      width: 100%;
      height: 180px;
      margin: 0;
    }
  }
  :deep(.el-upload-list--picture-card .el-upload-list__item:hover .el-upload-list__item-status-label) {
    display: inline-flex !important;
    opacity: 1 !important;
  }
  :deep(.el-upload-list__item.is-success:focus .el-upload-list__item-status-label) {
    display: inline-flex !important;
    opacity: 1 !important;
  }
  :deep(.el-upload-list--picture-card .el-icon--close-tip) {
    display: none !important;
  }
  &.upload-full {
    :deep(.el-upload--picture-card) {
      display: none !important;
    }
  }

  // 21:9横向图片样式
  &.upload-area-horizontal-21-9 {
    :deep(.el-upload--picture-card) {
      width: 100%;
      height: auto;
      aspect-ratio: 21 / 9;
    }
    :deep(.el-upload-list--picture-card) {
      width: 100%;
      .el-upload-list__item {
        width: 100%;
        height: auto;
        aspect-ratio: 21 / 9;
        margin: 0;
      }
    }
  }

  // 竖版图片样式
  &.upload-area-vertical {
    :deep(.el-upload--picture-card) {
      width: 150px;
      height: 150px;
    }
    :deep(.el-upload-list--picture-card) {
      .el-upload-list__item {
        width: 150px;
        height: 150px;
        margin: 0;
      }
    }
  }
}
.upload-trigger-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  font-size: 28px;
  color: #8c939d;
}

/* el-upload 图片预览铺满容器 */
:deep(.el-upload-list--picture-card) {
  .el-upload-list__item {
    margin: 0;
    overflow: hidden;
    .el-upload-list__item-thumbnail {
      width: 100%;
      height: 100%;

      //object-fit: fill;
    }
  }
  .el-upload-list__item[data-status="ready"],
  .el-upload-list__item.is-ready {
    position: relative;
    pointer-events: none;
    cursor: not-allowed;
    opacity: 0.6;
    &::after {
      position: absolute;
      inset: 0;
      z-index: 1;
      content: "";
      background-color: rgb(0 0 0 / 30%);
    }
    .el-upload-list__item-actions {
      pointer-events: none;
      opacity: 0.5;
    }
  }
  .el-upload-list__item:hover .el-upload-list__item-status-label {
    display: inline-flex !important;
    opacity: 1 !important;
  }
  .el-upload-list__item.is-success:focus .el-upload-list__item-status-label {
    display: inline-flex !important;
    opacity: 1 !important;
  }
  .el-icon--close-tip {
    display: none !important;
  }
}
</style>
