import axios from "axios";
import { buildOssDirPath } from "./env";

// ==================== 类型定义 ====================

/**
 * OSS 直传 Token 响应
 */
export interface OssToken {
  /** OSS 访问 ID */
  accessid: string;
  /** Base64 编码的 Policy */
  policy: string;
  /** 签名 */
  signature: string;
  /** 上传目录前缀 */
  dir: string;
  /** OSS 上传地址（https://bucketname.endpoint） */
  host: string;
  /** 完整文件路径（dir + 日期路径 + UUID文件名） */
  key: string;
  /** 过期时间（秒） */
  expire: number;
}

/**
 * 上传结果
 */
export interface UploadResult {
  success: boolean;
  filePath: string;
  fileName: string;
  fileSize: number;
  mimeType: string;
}

// ==================== 配置 ====================

/**
 * 后端 API 基础地址
 * 根据你的项目修改此值
 */
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || "/api";

// ==================== 核心方法 ====================

/**
 * 获取阿里云 OSS 直传 Token
 *
 * @param fileName 文件名（如：图片.jpg）
 * @param dir 业务目录（如：avatar, course/cover），会自动添加环境前缀
 * @returns OSS 直传 Token
 */
export async function getOssToken(
  fileName: string,
  dir?: string,
): Promise<OssToken> {
  // 自动添加环境前缀（dev/test/prod）
  const fullDir = buildOssDirPath(dir);

  const response = await axios.get<{ code: number; data: OssToken }>(
    `${API_BASE_URL}/v1/files/oss/token`,
    {
      params: { fileName, dir: fullDir },
    },
  );
  return response.data.data;
}

/**
 * 直接上传文件到阿里云 OSS
 *
 * 使用 FormData + POST 方式直传，无需经过后端中转。
 * 支持：进度回调、取消上传、超时设置。
 *
 * @param file 要上传的文件
 * @param token OSS Token（通过 getOssToken 获取）
 * @param options 可选配置
 * @returns 上传后的文件 URL
 */
export async function uploadToOss(
  file: File,
  token: OssToken,
  options?: {
    /** 上传进度回调（0-100） */
    onProgress?: (percent: number) => void;
    /** 取消信号 */
    signal?: AbortSignal;
    /** 超时时间（毫秒），默认 5 分钟 */
    timeout?: number;
  },
): Promise<{ url: string }> {
  const opts = options ?? {};
  const formData = new FormData();

  // 按照阿里云 OSS PostObject 要求构造表单
  // 注意：file 必须为最后一个表单域
  formData.append("success_action_status", "200"); // 成功时返回 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); // file 必须为最后一个表单域

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

  return {
    url: `${token.host}/${token.key}`,
  };
}

/**
 * 一站式上传文件（获取 Token + 直传 OSS）
 *
 * @param file 要上传的文件
 * @param dir 业务目录（如：avatar, course/cover）
 * @param options 可选配置
 * @returns 上传结果
 */
export async function uploadFile(
  file: File,
  dir?: string,
  options?: {
    onProgress?: (percent: number) => void;
    signal?: AbortSignal;
  },
): Promise<UploadResult> {
  // 1. 获取 OSS 直传 Token
  const token = await getOssToken(file.name, dir);

  // 2. 直传到 OSS
  await uploadToOss(file, token, {
    onProgress: options?.onProgress,
    signal: options?.signal,
  });

  // 3. 返回结果
  return {
    success: true,
    filePath: `${token.host}/${token.key}`,
    fileName: file.name,
    fileSize: file.size,
    mimeType: file.type,
  };
}
