/**
 * 图片压缩工具 - 使用原生 Canvas API
 * 将图片压缩到指定最大尺寸（1024x1024px）
 */

export interface ResizeOptions {
  maxWidth?: number
  maxHeight?: number
  quality?: number
  outputFormat?: 'image/jpeg' | 'image/png' | 'image/webp'
  mode?: 'contain' | 'cover' | 'crop' // contain: 等比缩放, cover: 填充裁剪, crop: 居中裁剪
}

const DEFAULT_OPTIONS: Required<ResizeOptions> = {
  maxWidth: 1024,
  maxHeight: 1024,
  quality: 0.92,
  outputFormat: 'image/jpeg',
  mode: 'contain'
}

/**
 * 使用 Canvas API 压缩图片
 * @param file 原始图片文件
 * @param options 压缩选项
 * @returns 压缩后的 Blob
 */
export async function resizeImageWithCanvas(
  file: File,
  options: ResizeOptions = {}
): Promise<Blob> {
  const opts = { ...DEFAULT_OPTIONS, ...options }
  
  return new Promise((resolve, reject) => {
    const img = new Image()
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    
    if (!ctx) {
      reject(new Error('Canvas context not available'))
      return
    }

    const objectUrl = URL.createObjectURL(file)

    img.onload = () => {
      try {
        let { width, height } = img
        
        // 如果图片尺寸已经小于等于目标尺寸，直接返回原图
        if (width <= opts.maxWidth && height <= opts.maxHeight) {
          URL.revokeObjectURL(objectUrl)
          // 直接读取原文件为 blob
          file.arrayBuffer().then(buffer => {
            resolve(new Blob([buffer], { type: file.type }))
          }).catch(reject)
          return
        }
        
        // 计算目标尺寸
        let targetWidth = width
        let targetHeight = height
        let sourceX = 0
        let sourceY = 0
        let sourceWidth = width
        let sourceHeight = height

        if (opts.mode === 'contain') {
          // 等比缩放，保持宽高比
          const scale = Math.min(
            opts.maxWidth / width,
            opts.maxHeight / height,
            1 // 不放大
          )
          targetWidth = Math.round(width * scale)
          targetHeight = Math.round(height * scale)
        } else if (opts.mode === 'cover') {
          // 填充模式：裁剪以填满目标尺寸
          const scale = Math.max(
            opts.maxWidth / width,
            opts.maxHeight / height
          )
          targetWidth = opts.maxWidth
          targetHeight = opts.maxHeight
          sourceWidth = Math.round(opts.maxWidth / scale)
          sourceHeight = Math.round(opts.maxHeight / scale)
          sourceX = Math.round((width - sourceWidth) / 2)
          sourceY = Math.round((height - sourceHeight) / 2)
        } else if (opts.mode === 'crop') {
          // 居中裁剪到目标尺寸
          const scale = Math.max(
            opts.maxWidth / width,
            opts.maxHeight / height
          )
          const scaledWidth = width * scale
          const scaledHeight = height * scale
          targetWidth = opts.maxWidth
          targetHeight = opts.maxHeight
          sourceWidth = width
          sourceHeight = height
          // 计算裁剪区域
          if (scaledWidth > opts.maxWidth) {
            sourceX = Math.round((scaledWidth - opts.maxWidth) / 2 / scale)
            sourceWidth = Math.round(opts.maxWidth / scale)
          }
          if (scaledHeight > opts.maxHeight) {
            sourceY = Math.round((scaledHeight - opts.maxHeight) / 2 / scale)
            sourceHeight = Math.round(opts.maxHeight / scale)
          }
        }

        // 设置 canvas 尺寸
        canvas.width = targetWidth
        canvas.height = targetHeight

        // 设置图片质量（仅对 JPEG 有效）
        if (opts.outputFormat === 'image/jpeg') {
          ctx.fillStyle = '#FFFFFF'
          ctx.fillRect(0, 0, targetWidth, targetHeight)
        }

        // 绘制图片
        ctx.drawImage(
          img,
          sourceX, sourceY, sourceWidth, sourceHeight,
          0, 0, targetWidth, targetHeight
        )

        // 转换为 Blob
        canvas.toBlob(
          (blob) => {
            // 清理对象 URL
            URL.revokeObjectURL(objectUrl)
            if (blob) {
              resolve(blob)
            } else {
              reject(new Error('Failed to create blob'))
            }
          },
          opts.outputFormat,
          opts.quality
        )
      } catch (error) {
        URL.revokeObjectURL(objectUrl)
        reject(error)
      }
    }

    img.onerror = () => {
      URL.revokeObjectURL(objectUrl)
      reject(new Error('Failed to load image'))
    }

    // 加载图片
    img.src = objectUrl
  })
}

/**
 * 压缩图片文件，返回新的 File 对象
 */
export async function compressImageFile(
  file: File,
  options: ResizeOptions = {}
): Promise<File> {
  const blob = await resizeImageWithCanvas(file, options)
  const opts = { ...DEFAULT_OPTIONS, ...options }
  
  // 确定文件扩展名
  let ext = 'jpg'
  if (opts.outputFormat === 'image/png') {
    ext = 'png'
  } else if (opts.outputFormat === 'image/webp') {
    ext = 'webp'
  }
  
  // 创建新的 File 对象，保持原始文件名但更新扩展名
  const fileName = file.name.replace(/\.[^.]+$/, '') + '.' + ext
  return new File([blob], fileName, {
    type: opts.outputFormat,
    lastModified: Date.now()
  })
}

