import { Injectable, Logger, BadRequestException } from '@nestjs/common';
import { extname, join, basename } from 'path';
import { promises as fs } from 'fs';

// 文件类型配置
const FILE_TYPE_CONFIG = {
  cover: {
    allowedMimeTypes: ['image/jpeg', 'image/png', 'image/webp'],
    maxSize: 10 * 1024 * 1024, // 10MB
    folder: 'covers',
  },
  ebook: {
    allowedMimeTypes: [
      'application/pdf',
      'application/vnd.ms-powerpoint',
      'application/vnd.openxmlformats-officedocument.presentationml.presentation',
    ],
    maxSize: 300 * 1024 * 1024, // 300MB
    folder: 'ebooks',
  },
  audio: {
    allowedMimeTypes: ['audio/mpeg', 'audio/wav', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/ogg'],
    maxSize: 300 * 1024 * 1024, // 300MB
    folder: 'audio',
  },
  video: {
    allowedMimeTypes: ['video/mp4', 'video/webm', 'video/quicktime', 'video/x-msvideo'],
    maxSize: 300 * 1024 * 1024, // 300MB
    folder: 'videos',
  },
  ppt: {
    allowedMimeTypes: [
      'application/vnd.ms-powerpoint',
      'application/vnd.openxmlformats-officedocument.presentationml.presentation',
      'application/pdf', // 也允许PDF格式
    ],
    maxSize: 300 * 1024 * 1024, // 300MB
    folder: join('materials', 'ppt'),
  },
  poster: {
    allowedMimeTypes: ['image/jpeg', 'image/png', 'image/webp'],
    maxSize: 10 * 1024 * 1024, // 10MB
    folder: join('materials', 'posters'),
  },
  document: {
    allowedMimeTypes: [
      'application/msword',
      'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    ],
    maxSize: 300 * 1024 * 1024, // 300MB
    folder: 'documents',
  },
  other: {
    allowedMimeTypes: [
      'application/pdf',
      'application/msword',
      'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
      'application/vnd.ms-excel',
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      'image/jpeg',
      'image/png',
      'image/gif',
      'image/webp',
    ],
    maxSize: 300 * 1024 * 1024, // 300MB
    folder: 'other',
  },
};

@Injectable()
export class FileUploadService {
  private readonly logger = new Logger(FileUploadService.name);
  private readonly uploadBasePath = join(process.cwd(), 'uploads', 'courses');

  constructor() {
    this.ensureDirectoriesExist();
  }

  /**
   * 确保所有必要的目录存在
   */
  private async ensureDirectoriesExist() {
    const directories = Object.values(FILE_TYPE_CONFIG).map((config) =>
      join(this.uploadBasePath, config.folder),
    );

    for (const dir of directories) {
      try {
        await fs.mkdir(dir, { recursive: true });
        this.logger.log(`Ensured directory exists: ${dir}`);
      } catch (error) {
        this.logger.error(`Failed to create directory ${dir}:`, error);
      }
    }
  }

  /**
   * 验证文件
   */
  validateFile(
    file: Express.Multer.File,
    type: string,
  ): { valid: boolean; error?: string } {
    const config = FILE_TYPE_CONFIG[type as keyof typeof FILE_TYPE_CONFIG] || FILE_TYPE_CONFIG.other;

    // 检查文件大小
    if (file.size > config.maxSize) {
      const maxSizeMB = (config.maxSize / (1024 * 1024)).toFixed(0);
      return {
        valid: false,
        error: `文件大小超过限制，最大允许 ${maxSizeMB}MB`,
      };
    }

    // 检查 MIME 类型
    if (!config.allowedMimeTypes.includes(file.mimetype)) {
      return {
        valid: false,
        error: `不支持的文件类型: ${file.mimetype}`,
      };
    }

    return { valid: true };
  }

  /**
   * 保存文件
   */
  async saveFile(
    file: Express.Multer.File,
    type: string,
    courseId?: string,
  ): Promise<{ filePath: string; fileName: string }> {
    const config = FILE_TYPE_CONFIG[type as keyof typeof FILE_TYPE_CONFIG] || FILE_TYPE_CONFIG.other;

    // 生成安全的文件名（避免中文和特殊字符编码问题）
    const timestamp = Date.now();
    const randomStr = Math.random().toString(36).substring(2, 8);
    const originalExt = extname(file.originalname) || '';
    const courseIdPrefix = courseId ? `${courseId}_` : '';
    const newFileName = `${courseIdPrefix}${timestamp}_${randomStr}${originalExt}`;

    // 目标路径
    const targetDir = join(this.uploadBasePath, config.folder);
    const targetPath = join(targetDir, newFileName);

    try {
      // 写入文件
      await fs.writeFile(targetPath, file.buffer);

      // 返回相对路径（用于 API 响应和数据库存储）
      const relativePath = `/uploads/courses/${config.folder}/${newFileName}`;

      this.logger.log(`File saved: ${targetPath}`);

      return {
        filePath: relativePath,
        fileName: newFileName,
      };
    } catch (error) {
      this.logger.error('Failed to save file:', error);
      throw new BadRequestException('文件保存失败');
    }
  }

  /**
   * 删除文件
   */
  async deleteFile(filePath: string): Promise<{ success: boolean; error?: string }> {
    try {
      // 安全检查：确保路径在 uploads 目录内，防止目录遍历攻击
      if (!filePath.startsWith('/uploads/')) {
        return { success: false, error: '非法的文件路径' };
      }

      // 防止路径遍历攻击
      const normalizedPath = filePath.replace(/\.\./g, '');
      const fullPath = join(process.cwd(), normalizedPath);

      // 确保最终路径仍在 uploads 目录内
      if (!fullPath.startsWith(join(process.cwd(), 'uploads'))) {
        return { success: false, error: '非法的文件路径' };
      }

      // 检查文件是否存在
      try {
        await fs.access(fullPath);
      } catch {
        this.logger.warn(`File not found: ${fullPath}`);
        return { success: true, error: '文件不存在' }; // 文件不存在也返回成功
      }

      // 删除文件
      await fs.unlink(fullPath);
      this.logger.log(`File deleted: ${fullPath}`);

      return { success: true };
    } catch (error) {
      this.logger.error('Failed to delete file:', error);
      return { success: false, error: '文件删除失败' };
    }
  }
}
