import { Injectable } from '@angular/core';
import { NovaUploadService as FmodeUploadService } from 'fmode-ng/storage';

/**
 * 文件上传服务
 * 用于处理图片、视频、文档等文件的上传
 * 基于 fmode-ng 的 NovaUploadService
 */
@Injectable({
  providedIn: 'root'
})
export class ProjectUploadService {
  constructor(private uploadServ: FmodeUploadService) {}

  /**
   * 上传单个文件
   * @param file File对象
   * @param options 上传选项
   * @returns 上传后的文件URL
   */
  async uploadFile(
    file: File,
    options?: {
      onProgress?: (progress: number) => void;
      compress?: boolean;
      maxWidth?: number;
      maxHeight?: number;
    }
  ): Promise<string> {
    try {
      let fileToUpload = file;

      // 如果是图片且需要压缩
      if (options?.compress && file.type.startsWith('image/')) {
        fileToUpload = await this.compressImage(file, {
          maxWidth: options.maxWidth || 1920,
          maxHeight: options.maxHeight || 1920,
          quality: 0.8
        });
      }

      // 使用 fmode-ng 的上传服务
      const fileResult = await this.uploadServ.upload(fileToUpload, (progress: any) => {
        if (options?.onProgress && progress?.percent) {
          options.onProgress(progress.percent);
        }
      });

      // 返回文件URL
      return fileResult.url || '';
    } catch (error: any) {
      console.error('文件上传失败:', error);
      throw new Error('文件上传失败: ' + (error?.message || '未知错误'));
    }
  }

  /**
   * 批量上传文件
   * @param files File数组
   * @param options 上传选项
   * @returns 上传后的文件URL数组
   */
  async uploadFiles(
    files: File[],
    options?: {
      onProgress?: (current: number, total: number) => void;
      compress?: boolean;
    }
  ): Promise<string[]> {
    const urls: string[] = [];
    const total = files.length;

    for (let i = 0; i < files.length; i++) {
      const url = await this.uploadFile(files[i], {
        compress: options?.compress
      });
      urls.push(url);
      options?.onProgress?.(i + 1, total);
    }

    return urls;
  }

  /**
   * 压缩图片
   * @param file 原始文件
   * @param options 压缩选项
   * @returns 压缩后的File对象
   */
  private compressImage(
    file: File,
    options: {
      maxWidth: number;
      maxHeight: number;
      quality: number;
    }
  ): Promise<File> {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();

      reader.onload = (e) => {
        const img = new Image();

        img.onload = () => {
          const canvas = document.createElement('canvas');
          let { width, height } = img;

          // 计算压缩后的尺寸
          if (width > options.maxWidth || height > options.maxHeight) {
            const ratio = Math.min(
              options.maxWidth / width,
              options.maxHeight / height
            );
            width = width * ratio;
            height = height * ratio;
          }

          canvas.width = width;
          canvas.height = height;

          const ctx = canvas.getContext('2d');
          ctx?.drawImage(img, 0, 0, width, height);

          canvas.toBlob(
            (blob) => {
              if (blob) {
                const compressedFile = new File([blob], file.name, {
                  type: file.type,
                  lastModified: Date.now()
                });
                resolve(compressedFile);
              } else {
                reject(new Error('图片压缩失败'));
              }
            },
            file.type,
            options.quality
          );
        };

        img.onerror = () => reject(new Error('图片加载失败'));
        img.src = e.target?.result as string;
      };

      reader.onerror = () => reject(new Error('文件读取失败'));
      reader.readAsDataURL(file);
    });
  }

  /**
   * 生成缩略图
   * @param file 原始图片文件
   * @param size 缩略图尺寸
   * @returns 缩略图URL
   */
  async generateThumbnail(file: File, size: number = 200): Promise<string> {
    const thumbnailFile = await this.compressImage(file, {
      maxWidth: size,
      maxHeight: size,
      quality: 0.7
    });

    return await this.uploadFile(thumbnailFile);
  }

  /**
   * 从URL下载文件
   * @param url 文件URL
   * @param filename 保存的文件名
   */
  async downloadFile(url: string, filename: string): Promise<void> {
    try {
      const response = await fetch(url);
      const blob = await response.blob();
      const link = document.createElement('a');
      link.href = URL.createObjectURL(blob);
      link.download = filename;
      link.click();
      URL.revokeObjectURL(link.href);
    } catch (error) {
      console.error('文件下载失败:', error);
      throw new Error('文件下载失败');
    }
  }

  /**
   * 验证文件类型
   * @param file 文件
   * @param allowedTypes 允许的MIME类型数组
   * @returns 是否合法
   */
  validateFileType(file: File, allowedTypes: string[]): boolean {
    return allowedTypes.some(type => {
      if (type.endsWith('/*')) {
        const prefix = type.replace('/*', '');
        return file.type.startsWith(prefix);
      }
      return file.type === type;
    });
  }

  /**
   * 验证文件大小
   * @param file 文件
   * @param maxSizeMB 最大大小(MB)
   * @returns 是否合法
   */
  validateFileSize(file: File, maxSizeMB: number): boolean {
    const maxSizeBytes = maxSizeMB * 1024 * 1024;
    return file.size <= maxSizeBytes;
  }

  /**
   * 格式化文件大小
   * @param bytes 字节数
   * @returns 格式化后的字符串
   */
  formatFileSize(bytes: number): string {
    if (bytes < 1024) return bytes + ' B';
    if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + ' KB';
    if (bytes < 1024 * 1024 * 1024) return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
    return (bytes / (1024 * 1024 * 1024)).toFixed(2) + ' GB';
  }
}
