import { request, type ApiResponse } from '@/utils/request'
import axios from 'axios'

/** 上传响应 */
export interface UploadResponse {
  /** 文件URL */
  url: string
  /** 文件名 */
  fileName: string
  /** 文件大小 */
  fileSize: number
}

/** 预签名URL请求 */
export interface GetPresignedUrlRequest {
  /** 原始文件名 */
  fileName: string
  /** 文件MIME类型 */
  contentType: string
  /** 文件大小(字节) */
  fileSize: number
}

/** 预签名URL响应 */
export interface PresignedUrlResponse {
  /** 预签名上传URL */
  uploadUrl: string
  /** 文件最终访问URL */
  fileUrl: string
  /** 对象Key（COS路径） */
  objectKey: string
  /** URL过期时间（秒） */
  expiresIn: number
  /** 存储类型 */
  storageType: string
}

/** 不支持直传的响应 */
export interface DirectUploadNotSupportedResponse {
  supportsDirectUpload: false
}

/**
 * 获取预签名上传URL
 * @param params 请求参数
 * @returns 预签名URL信息
 */
export function getPresignedUrl(
  params: GetPresignedUrlRequest
): Promise<ApiResponse<PresignedUrlResponse | DirectUploadNotSupportedResponse>> {
  return request<PresignedUrlResponse | DirectUploadNotSupportedResponse>({
    url: '/admin/upload/presigned-url',
    method: 'POST',
    data: params
  })
}

/**
 * 直接上传文件到COS
 * @param uploadUrl 预签名上传URL
 * @param file 文件对象
 * @param contentType 文件MIME类型
 * @param onProgress 上传进度回调
 */
export async function uploadToCos(
  uploadUrl: string,
  file: File,
  contentType: string,
  onProgress?: (percent: number) => void
): Promise<void> {
  await axios.put(uploadUrl, file, {
    headers: {
      'Content-Type': contentType
    },
    onUploadProgress: (progressEvent) => {
      if (progressEvent.total && onProgress) {
        const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total)
        onProgress(percent)
      }
    }
  })
}

/**
 * 上传文件（智能选择直传或服务端上传）
 * @param file 文件对象
 * @param onProgress 上传进度回调
 * @returns 上传结果
 */
export async function uploadFile(
  file: File,
  onProgress?: (percent: number) => void
): Promise<ApiResponse<UploadResponse>> {
  // 1. 先尝试获取预签名URL
  const presignedRes = await getPresignedUrl({
    fileName: file.name,
    contentType: file.type || 'application/octet-stream',
    fileSize: file.size
  })

  // 2. 检查是否支持直传
  if (presignedRes.code === 0 && presignedRes.data) {
    const data = presignedRes.data
    
    // 检查是否支持直传
    if ('supportsDirectUpload' in data && data.supportsDirectUpload === false) {
      // 不支持直传，走服务端上传
      return uploadFileToServer(file, onProgress)
    }

    // 支持直传，直接上传到COS
    const presignedData = data as PresignedUrlResponse
    await uploadToCos(presignedData.uploadUrl, file, file.type || 'application/octet-stream', onProgress)

    // 返回上传结果
    return {
      code: 0,
      message: '上传成功',
      data: {
        url: presignedData.fileUrl,
        fileName: file.name,
        fileSize: file.size
      }
    }
  }

  // 获取预签名URL失败，降级到服务端上传
  console.warn('获取预签名URL失败，降级到服务端上传:', presignedRes.message)
  return uploadFileToServer(file, onProgress)
}

/**
 * 上传文件到服务端（降级方案）
 * @param file 文件对象
 * @param onProgress 上传进度回调
 * @returns 上传结果
 */
export function uploadFileToServer(
  file: File,
  onProgress?: (percent: number) => void
): Promise<ApiResponse<UploadResponse>> {
  const formData = new FormData()
  formData.append('file', file)

  return request<UploadResponse>({
    url: '/admin/upload/image',
    method: 'POST',
    data: formData,
    headers: {
      'Content-Type': 'multipart/form-data'
    },
    onUploadProgress: (progressEvent) => {
      if (progressEvent.total && onProgress) {
        const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total)
        onProgress(percent)
      }
    }
  })
}

/**
 * 批量上传文件
 * @param files 文件列表
 * @param onProgress 上传进度回调
 * @returns 上传结果列表
 */
export function uploadFiles(
  files: File[],
  onProgress?: (percent: number) => void
): Promise<ApiResponse<UploadResponse[]>> {
  const formData = new FormData()
  files.forEach((file) => {
    formData.append('files', file)
  })

  return request<UploadResponse[]>({
    url: '/admin/upload/images',
    method: 'POST',
    data: formData,
    headers: {
      'Content-Type': 'multipart/form-data'
    },
    onUploadProgress: (progressEvent) => {
      if (progressEvent.total && onProgress) {
        const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total)
        onProgress(percent)
      }
    }
  })
}
