import type { TreatyBody } from "@/api/types";
import { client, safeClient } from "@/api";

interface UploadOptions {
  fetchOptions: UploadFetchOptions;
  onProgress?: (progress: number) => void;
  signal?: AbortSignal;
}

export type UploadFetchOptions = TreatyBody<typeof client.api.file_storage.upload_url.post>;

export async function uploadToS3(file: File, options: UploadOptions) {
  const { onProgress, signal, fetchOptions } = options;

  // 1. 获取预签名 URL
  const { data, error } = await safeClient(client.api.file_storage.upload_url.post({
    ...fetchOptions,
  }));

  if (error.value || !data.value) {
    throw new Error("获取上传 URL 失败");
  }
  const { fileId, uploadUrl, method, headers } = toRefs(data.value);

  // 2. 上传文件到 S3
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();

    // 监听上传进度
    xhr.upload.addEventListener("progress", (e: ProgressEvent) => {
      if (e.lengthComputable && onProgress) {
        const progress = Math.round((e.loaded / e.total) * 100);
        onProgress(progress);
      }
    });

    // 上传成功
    xhr.addEventListener("load", () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        resolve(fileId.value);
      }
      else {
        reject(new Error(`上传失败: ${xhr.status} ${xhr.statusText}`));
      }
    });

    // 网络错误
    xhr.addEventListener("error", () => {
      reject(new Error("网络错误，上传失败"));
    });

    // 上传取消
    xhr.addEventListener("abort", () => {
      reject(new Error("上传已取消"));
    });

    // 超时
    xhr.addEventListener("timeout", () => {
      reject(new Error("上传超时"));
    });

    // 支持外部取消
    if (signal) {
      signal.addEventListener("abort", () => {
        xhr.abort();
      });
    }

    // 开始上传
    xhr.open(method.value, uploadUrl.value, true);
    for (const [key, value] of Object.entries(headers.value)) {
      xhr.setRequestHeader(key, value);
    }
    xhr.timeout = 300000; // 5分钟超时
    xhr.send(file);
  });
}
