import axios from "axios";
import request from "@/utils/request";
import { buildOssDirPath } from "@/utils/oss-env";

/**
 * 上传响应接口（保持向后兼容）
 */
export interface UploadResponse {
  url: string;
  filename: string;
  originalname: string;
  size: number;
}

/**
 * OSS 直传 Token 响应
 */
interface OssToken {
  accessid: string;
  policy: string;
  signature: string;
  dir: string;
  host: string;
  key: string;
  expire: number;
}

/**
 * 上传选项
 */
interface UploadOptions {
  /** 上传进度回调（0-100） */
  onProgress?: (percent: number) => void;
  /** 取消信号 */
  signal?: AbortSignal;
}

/**
 * 获取 OSS 直传 Token
 */
async function getOssToken(
  fileName: string,
  dir?: string,
): Promise<OssToken> {
  const fullDir = buildOssDirPath(dir);
  const response = await request.get<OssToken>("/upload/oss/token", {
    params: { fileName, dir: fullDir },
  });
  return response;
}

/**
 * 直接上传文件到阿里云 OSS
 */
async function uploadToOss(
  file: File,
  token: OssToken,
  options?: UploadOptions,
): Promise<void> {
  const formData = new FormData();

  // 按照阿里云 OSS PostObject 要求构造表单
  // 注意：file 必须为最后一个表单域
  formData.append("success_action_status", "200");
  formData.append("OSSAccessKeyId", token.accessid);
  formData.append("policy", token.policy);
  formData.append("signature", token.signature);
  formData.append("key", token.key);
  formData.append("file", file);

  await axios.post(token.host, formData, {
    headers: {
      "Content-Type": "multipart/form-data",
    },
    timeout: 1000 * 60 * 5, // 默认 5 分钟
    signal: options?.signal,
    onUploadProgress: (progressEvent) => {
      if (options?.onProgress) {
        const percent =
          progressEvent.progress != null
            ? progressEvent.progress * 100
            : progressEvent.total
              ? (progressEvent.loaded * 100) / progressEvent.total
              : 0;
        options.onProgress(Math.round(percent));
      }
    },
  });
}

/**
 * 上传 API（保持接口兼容）
 */
export const uploadApi = {
  /**
   * 上传文件（通过 FormData）
   * @param formData 包含 file 字段的表单数据
   * @param dir 业务目录（如：homework/attachment）
   */
  upload: async (formData: FormData, dir?: string): Promise<UploadResponse> => {
    const file = formData.get("file") as File;
    return uploadFile(file, dir);
  },
};

/**
 * 上传单个文件（OSS 直传）
 *
 * @param file 要上传的文件
 * @param dir 业务目录（如：avatar, course/cover），会自动添加环境前缀
 * @param options 上传选项（进度回调、取消信号）
 */
export async function uploadFile(
  file: File,
  dir?: string,
  options?: UploadOptions,
): Promise<UploadResponse> {
  // 1. 获取 OSS 直传 Token
  const token = await getOssToken(file.name, dir);

  // 2. 直传到 OSS
  await uploadToOss(file, token, options);

  // 3. 返回结果（保持 UploadResponse 接口兼容）
  const url = `${token.host}/${token.key}`;
  return {
    url,
    filename: file.name,
    originalname: file.name,
    size: file.size,
  };
}
