<template>
  <div class="chunk-upload">
    <el-button type="primary" @click="handleClick" :disabled="uploading">
      {{ uploading ? '上传中...' : '选择并上传文件' }}
    </el-button>
    <div v-for="(progress, index) in uploadProgressList" :key="index" class="progress-item">
      <p>File {{ index + 1 }}: {{ progress.fileName }}</p>
      <el-progress :percentage="progress.percentage"></el-progress>
    </div>
    <input type="file" ref="fileInput" @change="handleFileChange" style="display: none;" multiple />
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";
import { ElMessage } from "element-plus";
import axios from "axios";
import { v1 as uuidv1 } from "uuid";

axios.defaults.baseURL = "http://10.181.7.236:9988";

export default defineComponent({
  name: "ChunkUpload",
  props: {
    maxFileSize: {
      type: Number,
      default: 10 * 1024 * 1024, // 默认10MB
    },
    maxFiles: {
      type: Number,
      default: 3, // 默认最大上传3个文件
    },
  },
  setup(props) {
    const fileInput = ref<HTMLInputElement | null>(null);
    const uploading = ref(false);
    const uploadedFileNames = ref<string[]>([]);
    const uploadProgressList = ref<{ fileName: string; percentage: number }[]>([]);
    const CHUNK_SIZE = 1 * 1024 * 1024; // 每个分片的大小为 1MB

    const handleClick = () => {
      fileInput.value?.click();
    };

    const handleFileChange = async (event: Event) => {
      const files = (event.target as HTMLInputElement).files;
      if (!files || files.length === 0) {
        return;
      }

      // 检查文件数量
      if (files.length > props.maxFiles) {
        ElMessage.error(`最多只能上传 ${props.maxFiles} 个文件`);
        return;
      }

      uploading.value = true;
      uploadProgressList.value = Array.from(files).map(file => ({
        fileName: file.name,
        percentage: 0,
      }));

      try {
        for (let i = 0; i < files.length; i++) {
          const file = files[i];
          if (file.size > props.maxFileSize) {
            ElMessage.error(`文件 ${file.name} 大小不能超过 ${props.maxFileSize / (1024 * 1024)} MB`);
            continue; // 跳过这个文件继续上传下一个
          }

          const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
          const fileIdentifier = await generateFileIdentifier();

          for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
            const start = chunkIndex * CHUNK_SIZE;
            const chunk = file.slice(start, start + CHUNK_SIZE);
            await uploadChunk(chunk, chunkIndex, totalChunks, fileIdentifier);
            uploadProgressList.value[i].percentage = Math.round(((chunkIndex + 1) / totalChunks) * 100);
          }

          // 文件分片上传完成后，调用合并接口
          const uuidFilename = await mergeChunks(fileIdentifier, file.name);
          uploadedFileNames.value.push(uuidFilename); // 保存上传成功的文件名
        }

        ElMessage.success("文件上传完成！");
      } catch (error) {
        ElMessage.error("文件上传失败！");
        console.error("Upload error:", error);
      } finally {
        uploading.value = false;
      }
    };

    const uploadChunk = async (
      chunk: Blob,
      chunkNumber: number,
      totalChunks: number,
      fileIdentifier: string
    ) => {
      const formData = new FormData();
      formData.append("file", chunk);

      try {
        await axios.post(`/api/file/upload/uploadfile`, formData, {
          params: {
            chunknumber: chunkNumber,
            identifier: fileIdentifier,
          },
          headers: {
            "Content-Type": "multipart/form-data",
          },
        });
      } catch (error) {
        throw new Error(`上传分片 ${chunkNumber} 失败`);
      }
    };

    const mergeChunks = async (identifier: string, filename: string) => {
      try {
        const response = await axios.post("/api/file/upload/mergefile", null, {
          params: {
            identifier: identifier,
            filename: filename,
            chunkstar: 0,  // 假设所有分片的开始序号为0
          },
        });

        if (response.status !== 200) {
          throw new Error("文件合并失败");
        }
        return response.data.uuidFilename;
      } catch (error) {
        throw new Error("合并请求失败");
      }
    };

    const generateFileIdentifier = async (): Promise<string> => {
      return uuidv1();  // 生成一个固定的 UUID1
    };

    const getUploadedFileNames = () => {
      return uploadedFileNames.value;
    };

    return {
      fileInput,
      uploading,
      uploadProgressList,
      handleClick,
      handleFileChange,
      getUploadedFileNames,
    };
  },
});
</script>

<style scoped>
.chunk-upload {
  padding: 20px;
}
.progress-item {
  margin-top: 10px;
}
</style>
