/**
 * 图片压缩工具类
 * 基于 CompressorJS 实现图片上传前压缩
 */
import Compressor from 'compressorjs';

export interface CompressorOptions {
  /** 压缩质量，0-1 之间，值越小文件越小但质量越差 */
  quality?: number;
  /** 最大宽度（像素） */
  maxWidth?: number;
  /** 最大高度（像素） */
  maxHeight?: number;
  /** 最小宽度 */
  minWidth?: number;
  /** 最小高度 */
  minHeight?: number;
  /** 固定宽度 */
  width?: number;
  /** 固定高度 */
  height?: number;
  /** 调整大小模式：'none' | 'contain' | 'cover' */
  resize?: 'none' | 'contain' | 'cover';
  /** 是否裁剪 */
  crop?: boolean;
  /** 旋转角度（度） */
  rotate?: number;
  /** 模糊半径 */
  blur?: number;
  /** 是否转为灰度图 */
  grayscale?: boolean;
  /** 输出类型：'blob' | 'base64' | 'datauristring' */
  output?: 'blob' | 'base64' | 'datauristring';
}

export interface BeforeUploadResult {
  file: File;
  compressed: boolean;
}

/**
 * 检查文件是否为图片
 * @param file 上传的文件
 */
export const isImage = (file: File): boolean => {
  return /^image\//.test(file.type);
};

/**
 * 默认压缩配置
 */
const DEFAULT_COMPRESS_OPTIONS: Required<CompressorOptions> = {
  quality: 0.8,
  maxWidth: 1280,
  maxHeight: 1280,
  minWidth: 0,
  minHeight: 0,
  width: Infinity,
  height: Infinity,
  resize: 'cover',
  crop: false,
  rotate: 0,
  blur: 0,
  grayscale: false,
  output: 'blob'
};

/**
 * 压缩单个图片文件
 * @param file 原始文件
 * @param options 压缩配置
 * @returns 压缩后的文件对象
 */
export const compressImage = (
  file: File,
  options: CompressorOptions = {}
): Promise<File> => {
  return new Promise((resolve, reject) => {
    // 合并默认配置
    const mergedOptions = { ...DEFAULT_COMPRESS_OPTIONS, ...options };

    new Compressor(file, {
      ...mergedOptions,
      success(result) {
        try {
          // 转换为 File 对象，保持原始文件名
          const targetType = file.type.includes('png') ? 'image/png' : 'image/jpeg';
          const compressedFile = new File([result], file.name, {
            type: targetType,
            lastModified: Date.now()
          });
          resolve(compressedFile);
        } catch (error) {
          reject(error);
        }
      },
      error(err) {
        reject(err);
      }
    });
  });
};

/**
 * 批量压缩图片文件
 * @param files 文件数组
 * @param options 压缩配置
 * @returns 压缩后的文件数组
 */
export const compressImages = async (
  files: File[],
  options: CompressorOptions = {}
): Promise<File[]> => {
  const promises = files.map(file => {
    if (isImage(file)) {
      return compressImage(file, options);
    }
    return Promise.resolve(file);
  });

  return Promise.all(promises);
};

/**
 * 带错误处理的图片压缩
 * 压缩失败时返回原文件
 * @param file 原始文件
 * @param options 压缩配置
 * @returns { file, compressed } 压缩结果
 */
export const compressImageSafe = async (
  file: File,
  options: CompressorOptions = {}
): Promise<BeforeUploadResult> => {
  try {
    // 仅压缩图片文件
    if (!isImage(file)) {
      return { file, compressed: false };
    }

    const compressedFile = await compressImage(file, options);
    return {
      file: compressedFile,
      compressed: true
    };
  } catch (error) {
    console.error('图片压缩失败，使用原文件:', error);
    return { file, compressed: false };
  }
};

/**
 * Element Plus :before-upload 钩子函数
 * 自动压缩图片并返回压缩后的文件
 * @param rawFile 原始文件
 * @param options 压缩配置
 * @returns Promise<File | boolean> 返回文件或布尔值
 */
export const beforeImageUpload = (
  rawFile: File,
  options: CompressorOptions = {}
): Promise<File | boolean> => {
  // 首先进行基本验证
  const isValidImage = isImage(rawFile);
  const isValidType = ['image/jpeg', 'image/png', 'image/webp'].includes(rawFile.type);
  const isValidSize = rawFile.size < 50 * 1024 * 1024; // 50MB

  if (!isValidImage || !isValidType) {
    return Promise.resolve(false);
  }

  if (!isValidSize) {
    return Promise.resolve(false);
  }

  // 压缩图片
  return compressImageSafe(rawFile, options).then(result => {
    return result.file;
  });
};

/**
 * Element Plus :before-upload 钩子函数（严格模式）
 * 压缩失败时拒绝上传
 * @param rawFile 原始文件
 * @param options 压缩配置
 * @returns Promise<File | boolean> 返回文件或布尔值
 */
export const beforeImageUploadStrict = (
  rawFile: File,
  options: CompressorOptions = {}
): Promise<File | boolean> => {
  // 首先进行基本验证
  if (!['image/jpeg', 'image/png', 'image/webp'].includes(rawFile.type)) {
    return Promise.resolve(false);
  }

  if (rawFile.size > 50 * 1024 * 1024) {
    return Promise.resolve(false);
  }

  // 压缩图片，失败则拒绝上传
  return compressImage(rawFile, options);
};

/**
 * 图片质量级别枚举
 */
export enum ImageQuality {
  /** 高质量（适合产品图、头像） */
  HIGH = 0.9,
  /** 中等质量（适合一般场景） */
  MEDIUM = 0.8,
  /** 高压缩（适合缩略图、证明材料） */
  LOW = 0.6
}

/**
 * 根据质量级别获取压缩配置
 * @param quality 质量级别
 * @param maxWidth 最大宽度
 * @param maxHeight 最大高度
 * @returns 压缩配置
 */
export const getQualityConfig = (
  quality: ImageQuality = ImageQuality.MEDIUM,
  maxWidth: number = 1280,
  maxHeight: number = 1280
): CompressorOptions => {
  return {
    quality,
    maxWidth,
    maxHeight
  };
};
