/**
 * 跨端图片压缩工具
 *
 * 用途：上传附件前压缩图片，避免大图（特别是手机原图 4MB+）导致上传卡死
 *
 * - H5：用 Canvas 重绘 + toDataURL('image/jpeg', quality)
 * - 小程序/APP：用 uni.compressImage API（quality + compressedWidth）
 *
 * 策略：
 *   - 原图小于 500KB 不压（避免无谓耗时）
 *   - 最大宽度限制 1280px（横屏照片）或按比例缩放
 *   - JPEG 质量 0.75（体积约 1/5 ~ 1/10，肉眼几乎无差）
 *   - 透明 PNG 也压成 JPEG（牺牲透明通道换取体积），如需透明可改 quality 调用
 *
 * 用法：
 *   import { compressImage } from '@/utils/imageCompress'
 *   const compressed = await compressImage(filePath)
 *   uploadFile({ filePath: compressed, ... })
 */

/** 不压缩的体积阈值（字节），800KB（小图直接跳过，避免无谓耗时） */
const SKIP_COMPRESS_SIZE = 800 * 1024
/** 最大边长，超过按比例缩放（保留宽高比）。1920px 兼顾清晰度与体积 */
const MAX_SIDE = 1920
/** JPEG 压缩质量 0~1。0.85 可保证医疗单据/药品说明书文字清晰 */
const JPEG_QUALITY = 0.85

/**
 * H5 端压缩：Canvas 重绘 + toBlob
 */
function compressH5(filePath: string): Promise<string> {
  return new Promise((resolve, reject) => {
    const img = new Image()
    img.crossOrigin = 'anonymous'
    img.onload = () => {
      try {
        // 计算缩放后的尺寸
        let { width, height } = img
        const longSide = Math.max(width, height)
        if (longSide > MAX_SIDE) {
          const scale = MAX_SIDE / longSide
          width = Math.round(width * scale)
          height = Math.round(height * scale)
        }
        // 创建 canvas 重绘
        const canvas = document.createElement('canvas')
        canvas.width = width
        canvas.height = height
        const ctx = canvas.getContext('2d')
        if (!ctx) {
          resolve(filePath) // 极端情况降级到原图
          return
        }
        // 白底（防止 PNG 透明通道转 JPEG 后变黑）
        ctx.fillStyle = '#ffffff'
        ctx.fillRect(0, 0, width, height)
        ctx.drawImage(img, 0, 0, width, height)
        // 转成 Blob 返回 ObjectURL（避免 base64 体积膨胀）
        canvas.toBlob(
          (blob) => {
            if (!blob) {
              resolve(filePath)
              return
            }
            // 释放旧的 ObjectURL（如果是 blob: URL）
            if (filePath.startsWith('blob:')) {
              try { URL.revokeObjectURL(filePath) } catch (e) { /* ignore */ }
            }
            resolve(URL.createObjectURL(blob))
          },
          'image/jpeg',
          JPEG_QUALITY
        )
      } catch (err) {
        console.warn('[imageCompress] H5 压缩失败，降级原图', err)
        resolve(filePath)
      }
    }
    img.onerror = (err) => {
      console.warn('[imageCompress] H5 图片加载失败，降级原图', err)
      resolve(filePath)
    }
    img.src = filePath
  })
}

/**
 * 小程序/APP 端压缩：uni.compressImage
 */
function compressMP(filePath: string): Promise<string> {
  return new Promise((resolve) => {
    uni.compressImage({
      src: filePath,
      quality: Math.round(JPEG_QUALITY * 100), // 75
      compressedWidth: MAX_SIDE,
      success: (res) => resolve(res.tempFilePath),
      fail: (err) => {
        console.warn('[imageCompress] uni.compressImage 失败，降级原图', err)
        resolve(filePath) // 失败降级
      }
    })
  })
}

/**
 * 获取文件大小（字节）。
 * - H5: blob: / data: URL 用 fetch 解析
 * - 小程序/APP: uni.getFileInfo
 */
function getFileSize(filePath: string): Promise<number> {
  return new Promise((resolve) => {
    // #ifdef H5
    try {
      if (filePath.startsWith('blob:') || filePath.startsWith('data:')) {
        fetch(filePath)
          .then(r => r.blob())
          .then(b => resolve(b.size))
          .catch(() => resolve(0))
        return
      }
    } catch (e) { /* fallthrough */ }
    resolve(0) // 无法获取则不压缩（保守策略）
    return
    // #endif
    // #ifndef H5
    uni.getFileInfo({
      filePath,
      success: (res) => resolve(res.size),
      fail: () => resolve(0)
    })
    // #endif
  })
}

/**
 * 压缩图片入口（跨端）
 * @param filePath 图片临时路径
 * @returns 压缩后的图片路径（如失败则返回原路径）
 */
export async function compressImage(filePath: string): Promise<string> {
  if (!filePath) return filePath
  try {
    // 检查体积，小图直接跳过
    const size = await getFileSize(filePath)
    if (size > 0 && size < SKIP_COMPRESS_SIZE) {
      return filePath
    }
    // #ifdef H5
    return await compressH5(filePath)
    // #endif
    // #ifndef H5
    return await compressMP(filePath)
    // #endif
  } catch (err) {
    console.warn('[imageCompress] 压缩过程异常，降级原图', err)
    return filePath
  }
}

/**
 * 批量压缩图片（串行执行，避免一次性占用过多内存）
 * @param filePaths 图片路径数组
 * @returns 压缩后的路径数组（与入参顺序一致）
 */
export async function compressImages(filePaths: string[]): Promise<string[]> {
  const result: string[] = []
  for (const p of filePaths) {
    result.push(await compressImage(p))
  }
  return result
}
