import { blobToBase64 } from "@/utils/file";
import { ElMessage } from "element-plus";
import { $ajax } from ".";
import { sha256 } from "js-sha256";

// 分块文件检查
export function fileCheck(query: any) {
  return $ajax({
    url: "/api/file/chunk/check",
    type: "get",
    params: query,
  });
}
// 文件合并
export function fileMerge(data: any) {
  return $ajax({
    url: "/api/file/chunk/merge",
    type: "post",
    params: data,
  });
}

export function fileUnzip(data: {
  category_id: number;
  file_name: string;
  file_hash: string;
}) {
  return $ajax({
    url: "/api/file/chunk/unzip",
    type: "post",
    params: data,
  });
}
// 分块文件上传
export function fileUpload(data: any) {
  return $ajax({
    url: "/api/file/chunk/upload",
    type: "post",
    params: data,
  });
}
// 批量获取文件
export function getFiles(query: any) {
  return $ajax({
    url: `/api/files?${query}`,
    type: "get",
  });
}

export async function handleBigFileUpload(
  file: File,
  onPercentCompleteChange?: (percent: number) => void
) {
  return new Promise<{
    merge?: () => any;
    /**和专辑绑定关系 */
    unzip: (category_id: number) => Promise<any>;
  }>((rootResolve, rootReject) => {
    let __sendingAmount = 0;
    let __total = 0;
    let __sendingIncreasing = false;
    let __file: File | null = null;
    let __localHash: any[] = [];
    let __localObjects: any[] = [];

    //   合并文件
    function mergeChunkFile(current: { file_hash: string; file_name: string }) {
      fileMerge({
        file_hash: current.file_hash,
        file_name: current.file_name,
      }).then((res) => {
        __sendingAmount = 0;
        __total = 0;
        if (!res) {
          ElMessage.warning("上传失败，请重新上传");
          return;
        }
        ElMessage.success("上传成功");
        __localHash.push(res.data.file_hash);
        __localObjects.push(__file);
      });
    }
    //  上传文件
    function uploadFileChunk(
      current: {
        current_data: string; //当前块数据
        current_seq: number; // 当前块序号
        current_size: number; //当前块大小
        file_name: string; //文件名称
        file_hash: string; //文件hash
        total_seq: number; //总序号
        total_size: number; //总大小
      },
      length: number
    ) {
      let i = setInterval(() => {
        if (__sendingAmount - __total === 0) {
          __sendingIncreasing = true;
        }
        if (__sendingAmount - __total > 6) {
          __sendingIncreasing = false;
        }
        if (__sendingIncreasing) {
          clearInterval(i);
          __sendingAmount += 1;
          fileUpload(current).then((res) => {
            if (!res) {
              ElMessage({
                message: "上传失败，请重新上传",
                type: "warning",
              });
              rootReject();
              return;
            }
            __total += 1;
            onPercentCompleteChange &&
              onPercentCompleteChange(__total / sliceBuffer.length);
            if (__total === length) {
              rootResolve({
                merge: () => mergeChunkFile(current),
                unzip: (category_id: number) =>
                  fileUnzip({
                    file_hash: current.file_hash,
                    file_name: current.file_name,
                    category_id,
                  }),
              });
            }
          });
        }
      }, 500);
    }
    //  查询文件
    function checkFileChunkState(hash: any) {
      return new Promise((resolve) => {
        fileCheck(hash).then((res) => {
          resolve(res);
        });
      });
    }

    const sliceBuffer: Blob[] = [];
    let slicesize = file.size;
    while (slicesize > 1024 * 1024) {
      const blobPart = file.slice(
        sliceBuffer.length * 1024 * 1024,
        (sliceBuffer.length + 1) * 1024 * 1024
      );
      sliceBuffer.push(blobPart);
      slicesize -= 1024 * 1024;
    }
    if (slicesize > 0) {
      sliceBuffer.push(file.slice(sliceBuffer.length * 1024 * 1024, file.size));
    }
    //2.计算文件HASH
    const fileReader = new FileReader();
    //文件读取回调
    let fileHash = sha256.create();
    fileReader.onload = function (event: Event) {
      const result = (event!.target! as any).result;
      fileHash.update(result);
      fileHash.update(file.name);
      checkFileChunkState({ file_hash: fileHash.hex() }).then((res: any) => {
        if (!res) return;
        let { is_done, file_info } = res.data;
        if (is_done && file_info) {
          // 上传完成
          ElMessage({
            message: "上传成功",
            type: "success",
          });
          __localHash.push(res.data.file_hash);
          __localObjects.push(file_info);
          rootResolve({
            unzip: (category_id: number) =>
              fileUnzip({
                category_id,
                file_hash: res.data.file_hash,
                file_name: file_info.name,
              }),
          });
          return;
        }
        const chunkRequests: any[] = [];
        sliceBuffer.forEach((buffer, i) => {
          const current = {
            current_data: "", //当前块数据
            current_seq: i + 1, // 当前块序号
            current_size: buffer.size, //当前块大小
            file_name: file.name, //文件名称
            file_hash: fileHash.hex(), //文件hash
            total_seq: sliceBuffer.length, //总序号
            total_size: file.size, //总大小
          };
          blobToBase64(buffer).then((res: string) => {
            // 转化后的base64
            current.current_data = res;
            chunkRequests.push(uploadFileChunk(current, sliceBuffer.length));
          });
          // }
        });
        return Promise.all(chunkRequests);
      });
    };
    //读取失败回调
    fileReader.onerror = function (err: any) {
      // err.target.error;
      rootReject();
    };
    fileReader.readAsArrayBuffer(file);
  });
}
