<!-- 图片上传组件 -->
<template>
  <el-upload v-model:file-list="fileList" list-type="picture-card" :before-upload="handleBeforeUpload"
    :http-request="handleUpload" :on-success="handleSuccess" :on-progress="handleProgress" :on-error="handleError"
    :on-exceed="handleExceed" :accept="props.accept" :limit="props.limit" multiple :auto-upload="true"
    :on-change="handleFileChange">
    <el-icon>
      <Plus />
    </el-icon>
    <template #file="{ file }">
      <div style="width: 100%">
        <img class="el-upload-list__item-thumbnail" :src="file.url" />
        <span class="el-upload-list__item-actions">
          <!-- 预览 -->
          <span @click="handlePreviewImage(file.url!)">
            <el-icon>
              <ZoomIn />
            </el-icon>
          </span>
          <!-- 删除 -->
          <span @click="handleRemove(file.url!)">
            <el-icon>
              <Delete />
            </el-icon>
          </span>
        </span>
      </div>
    </template>
  </el-upload>

  <el-image-viewer v-if="previewVisible" :zoom-rate="1.2" :initial-index="previewImageIndex" :url-list="modelValue"
    @close="handlePreviewClose" />
</template>

<script setup lang="ts">
import { ref, watch, onMounted, PropType } from "vue";
import { ElMessage } from "element-plus";
import { UploadRawFile, UploadRequestOptions, UploadUserFile, UploadFileStatus } from "element-plus";
import FileAPI, { FileInfo } from "@/api/account/common";

// 定义Props
const props = defineProps({
  data: {
    type: Object,
    default: () => ({}),
  },
  name: {
    type: String,
    default: "file",
  },
  limit: {
    type: Number,
    default: 9,
  },
  maxFileSize: {
    type: Number,
    default: 10, // 单位：M
  },
  accept: {
    type: String,
    default: "image/*",
  },
});

// 定义Emits：新增 uploadStart 事件（触发开始上传，用于父级loading）
const emit = defineEmits(['upDataEvent', 'uploadAllSuccess', 'uploadStart']);

// 响应式数据
const previewVisible = ref(false);
const previewImageIndex = ref(0);
const progress = ref(0);
// 新增：跟踪是否已触发开始上传（避免重复触发）
const isUploadStarted = ref(false);
// 修复：defineModel 类型定义
const modelValue = defineModel<string[]>("modelValue", {
  type: Array as PropType<string[]>,
  required: true,
  default: () => [],
});

const fileList = ref<UploadUserFile[]>([]);
// 修复：用Map跟踪每个文件的上传状态（key=uid，value=是否完成），替代计数
const uploadingFiles = ref<Map<string, { status: 'pending' | 'success' | 'error', file: UploadUserFile }>>(new Map());

/**
 * 删除图片
 */
function handleRemove(imageUrl: string) {
  const index = modelValue.value.indexOf(imageUrl);
  if (index !== -1) {
    modelValue.value.splice(index, 1);
    // 同步删除fileList和上传状态跟踪
    const fileItem = fileList.value[index];
    if (fileItem?.uid) {
      uploadingFiles.value.delete(fileItem.uid);
    }
    fileList.value.splice(index, 1);
  }
  // 若删除后无上传中的文件，重置开始上传状态
  if (uploadingFiles.value.size === 0) {
    isUploadStarted.value = false;
  }
}

/**
 * 上传进度
 */
function handleProgress(event: any, uploadFile: UploadUserFile) {
  console.log(`文件${uploadFile.name}上传进度`, Math.round(event.percent));
}

/**
 * 修复：文件状态变化时跟踪（替代beforeUpload手动push）
 */
function handleFileChange(file: UploadUserFile, files: UploadUserFile[]) {
  // 仅跟踪新增的、待上传的文件
  if (file.status === 'ready' && !uploadingFiles.value.has(file.uid)) {
    uploadingFiles.value.set(file.uid, {
      status: 'pending',
      file
    });
    // 新增：触发开始上传事件（仅第一次上传时触发，避免重复）
    if (!isUploadStarted.value) {
      isUploadStarted.value = true;
      emit('uploadStart'); // 通知父级：开始上传，开启loading
    }
    emit('upDataEvent', true); // 开始上传，触发loading
  }
  // 同步fileList（避免重复）
  fileList.value = files;
}

/**
 * 上传前校验（仅保留校验逻辑，不再手动修改fileList）
 */
function handleBeforeUpload(file: UploadRawFile) {
  // 1. 文件类型校验
  const acceptTypes = props.accept.split(",").map((type) => type.trim());
  const isValidType = acceptTypes.some((type) => {
    if (type === "image/*") {
      return file.type.startsWith("image/");
    } else if (type.startsWith(".")) {
      return file.name.toLowerCase().endsWith(type);
    } else {
      return file.type === type;
    }
  });

  if (!isValidType) {
    ElMessage.warning(`上传文件的格式不正确，仅支持：${props.accept}`);
    return false;
  }

  // 2. 文件大小校验
  if (file.size > props.maxFileSize * 1024 * 1024) {
    ElMessage.warning(`上传图片不能大于${props.maxFileSize}M`);
    return false;
  }

  return true;
}

/**
 * 自定义上传逻辑
 */
function handleUpload(options: UploadRequestOptions) {
  return new Promise((resolve, reject) => {
    const file = options.file;
    const formData = new FormData();
    formData.append(props.name, file);

    // 附加参数
    Object.keys(props.data).forEach((key) => {
      formData.append(key, props.data[key]);
    });

    FileAPI.upload(formData)
      .then((data) => {
        resolve(data);
      })
      .catch((error) => {
        reject(error);
      });
  });
}

/**
 * 超出数量限制
 */
function handleExceed(files: File[], uploadFiles: UploadUserFile[]) {
  ElMessage.warning(`最多只能上传${props.limit}张图片`);
}

/**
 * 修复：单文件上传成功回调（精准更新+批量完成判断）
 */
const handleSuccess = (fileInfo: FileInfo, uploadFile: UploadUserFile) => {
  // 1. 精准匹配文件并更新状态
  if (uploadingFiles.value.has(uploadFile.uid)) {
    uploadingFiles.value.set(uploadFile.uid, {
      status: 'success',
      file: uploadFile
    });
    // 2. 更新fileList的url和状态
    const index = fileList.value.findIndex((f) => f.uid === uploadFile.uid);
    if (index !== -1) {
      fileList.value[index].url = fileInfo as string;
      fileList.value[index].status = "success" as UploadFileStatus;
      // 3. 同步更新modelValue（确保追加，而非替换）
      if (!modelValue.value.includes(fileInfo as string)) {
        modelValue.value.push(fileInfo as string);
      }
    }
  }

  // 4. 检查是否所有上传中的文件都完成
  checkAllUploadCompleted();
};

/**
 * 上传失败回调
 */
const handleError = (error: any, uploadFile: UploadUserFile) => {
  console.error(`文件${uploadFile.name}上传失败:`, error);
  ElMessage.error(`文件${uploadFile.name}上传失败: ` + (error.message || "未知错误"));

  // 更新失败文件状态
  if (uploadingFiles.value.has(uploadFile.uid)) {
    uploadingFiles.value.set(uploadFile.uid, {
      status: 'error',
      file: uploadFile
    });
  }

  // 检查是否所有上传中的文件都完成（失败也算完成）
  checkAllUploadCompleted();
};

/**
 * 新增：检查所有上传文件是否完成（成功/失败都算完成）
 */
function checkAllUploadCompleted() {
  // 过滤出还在pending的文件
  const pendingFiles = Array.from(uploadingFiles.value.values()).filter(item => item.status === 'pending');

  // 没有pending文件 → 所有上传完成
  if (pendingFiles.length === 0 && uploadingFiles.value.size > 0) {
    // 过滤出成功的文件URL
    const successUrls = Array.from(uploadingFiles.value.values())
      .filter(item => item.status === 'success')
      .map(item => item.file.url)
      .filter(Boolean) as string[];

    ElMessage.success(`上传完成！成功${successUrls.length}张，失败${uploadingFiles.value.size - successUrls.length}张`);
    emit('uploadAllSuccess', modelValue.value); // 触发全部完成事件
    emit('upDataEvent', false); // 结束loading

    // 新增：重置开始上传状态（下次上传可重新触发）
    isUploadStarted.value = false;

    // 重置上传状态跟踪（关键：避免多次触发）
    uploadingFiles.value.clear();
  }
}

/**
 * 预览图片
 */
const handlePreviewImage = (imageUrl: string) => {
  previewImageIndex.value = modelValue.value.findIndex((url) => url === imageUrl);
  previewVisible.value = true;
};

/**
 * 关闭预览
 */
const handlePreviewClose = () => {
  previewVisible.value = false;
};

// 修复：监听modelValue同步fileList（避免重复uid）
watch(modelValue, (newValue) => {
  fileList.value = newValue.map((url) => ({
    url,
    uid: `init-${Date.now()}-${Math.random()}`, // 为初始化图片生成唯一uid（避免和上传文件冲突）
    status: "success" as UploadFileStatus
  }));
}, { immediate: true });

onMounted(() => {
  // 初始化fileList
  fileList.value = modelValue.value.map((url) => ({
    url,
    uid: `init-${Date.now()}-${Math.random()}`,
    status: "success" as UploadFileStatus
  }));
});
</script>

<style lang="scss" scoped></style>