/**
 * 管理员文件管理控制器
 * 处理文件上传、管理、统计等功能
 */

const fs = require('fs');
const path = require('path');
const { AppError, ErrorTypes, catchAsync } = require('../../middleware/errorHandler');
const { logBusinessOperation, logError } = require('../../utils/logger');
const { deleteFile, getFileInfo } = require('../../middleware/upload');

/**
 * 获取文件列表
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 */
const getFileList = catchAsync(async (req, res) => {
  const {
    page = 1,
    limit = 20,
    type = 'all',
    keyword = '',
    start_date,
    end_date,
    sort_by = 'created_at',
    sort_order = 'desc'
  } = req.query;

  const offset = (page - 1) * limit;
  const uploadDir = path.join(__dirname, '../../../uploads');
  
  try {
    // 获取所有文件类型目录
    const typeDirs = {
      avatar: path.join(uploadDir, 'avatars'),
      animal: path.join(uploadDir, 'animals'),
      travel: path.join(uploadDir, 'travels'),
      document: path.join(uploadDir, 'documents')
    };
    
    let allFiles = [];
    
    // 根据类型筛选目录
    const dirsToScan = type === 'all' ? Object.values(typeDirs) : [typeDirs[type]];
    
    for (const dir of dirsToScan) {
      if (!fs.existsSync(dir)) continue;
      
      const files = fs.readdirSync(dir);
      const fileType = Object.keys(typeDirs).find(key => typeDirs[key] === dir);
      
      for (const file of files) {
        const filePath = path.join(dir, file);
        const stats = fs.statSync(filePath);
        
        // 跳过缩略图文件
        if (file.includes('_thumb')) continue;
        
        // 关键词筛选
        if (keyword && !file.toLowerCase().includes(keyword.toLowerCase())) {
          continue;
        }
        
        // 日期筛选
        if (start_date && stats.birthtime < new Date(start_date)) continue;
        if (end_date && stats.birthtime > new Date(end_date)) continue;
        
        const ext = path.extname(file).toLowerCase();
        const isImage = ['.jpg', '.jpeg', '.png', '.gif', '.webp'].includes(ext);
        
        allFiles.push({
          id: Buffer.from(filePath).toString('base64'),
          filename: file,
          originalName: file,
          type: fileType,
          size: stats.size,
          mimetype: isImage ? `image/${ext.slice(1)}` : 'application/octet-stream',
          isImage,
          url: `/uploads/${fileType}s/${file}`,
          thumbnailUrl: isImage ? `/uploads/${fileType}s/${file.replace(ext, '_thumb' + ext)}` : null,
          created_at: stats.birthtime,
          modified_at: stats.mtime
        });
      }
    }
    
    // 排序
    allFiles.sort((a, b) => {
      const aValue = a[sort_by] || a.created_at;
      const bValue = b[sort_by] || b.created_at;
      
      if (sort_order === 'desc') {
        return new Date(bValue) - new Date(aValue);
      } else {
        return new Date(aValue) - new Date(bValue);
      }
    });
    
    // 分页
    const total = allFiles.length;
    const files = allFiles.slice(offset, offset + parseInt(limit));
    
    // 记录操作日志
    logBusinessOperation('file_list_viewed', 'file', {
      page,
      limit,
      type,
      keyword,
      total
    }, req.user);
    
    res.json({
      success: true,
      message: '获取成功',
      data: {
        files,
        pagination: {
          current_page: parseInt(page),
          per_page: parseInt(limit),
          total,
          total_pages: Math.ceil(total / limit)
        }
      }
    });
  } catch (error) {
    logError(error, {
      type: 'file_list_error',
      userId: req.user?.id,
      query: req.query
    });
    throw ErrorTypes.INTERNAL_ERROR('获取文件列表失败');
  }
});

/**
 * 获取文件详情
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 */
const getFileDetail = catchAsync(async (req, res) => {
  const { file_id } = req.params;
  
  try {
    // 解码文件路径
    const filePath = Buffer.from(file_id, 'base64').toString();
    
    if (!fs.existsSync(filePath)) {
      throw ErrorTypes.NOT_FOUND('文件不存在');
    }
    
    const stats = fs.statSync(filePath);
    const filename = path.basename(filePath);
    const ext = path.extname(filename).toLowerCase();
    const isImage = ['.jpg', '.jpeg', '.png', '.gif', '.webp'].includes(ext);
    
    // 获取文件类型
    const uploadDir = path.join(__dirname, '../../../uploads');
    const relativePath = path.relative(uploadDir, filePath);
    const fileType = relativePath.split(path.sep)[0].replace('s', ''); // avatars -> avatar
    
    const fileDetail = {
      id: file_id,
      filename,
      originalName: filename,
      type: fileType,
      size: stats.size,
      mimetype: isImage ? `image/${ext.slice(1)}` : 'application/octet-stream',
      isImage,
      url: `/uploads/${fileType}s/${filename}`,
      thumbnailUrl: isImage ? `/uploads/${fileType}s/${filename.replace(ext, '_thumb' + ext)}` : null,
      created_at: stats.birthtime,
      modified_at: stats.mtime,
      path: relativePath
    };
    
    // 记录操作日志
    logBusinessOperation('file_detail_viewed', 'file', {
      fileId: file_id,
      filename
    }, req.user);
    
    res.json({
      success: true,
      message: '获取成功',
      data: {
        file: fileDetail
      }
    });
  } catch (error) {
    if (error instanceof AppError) {
      throw error;
    }
    
    logError(error, {
      type: 'file_detail_error',
      userId: req.user?.id,
      fileId: file_id
    });
    throw ErrorTypes.INTERNAL_ERROR('获取文件详情失败');
  }
});

/**
 * 删除文件
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 */
const deleteFileById = catchAsync(async (req, res) => {
  const { file_id } = req.params;
  
  try {
    // 解码文件路径
    const filePath = Buffer.from(file_id, 'base64').toString();
    const filename = path.basename(filePath);
    
    if (!fs.existsSync(filePath)) {
      throw ErrorTypes.NOT_FOUND('文件不存在');
    }
    
    // 删除文件
    const deleted = await deleteFile(filePath);
    
    if (!deleted) {
      throw ErrorTypes.INTERNAL_ERROR('文件删除失败');
    }
    
    // 记录操作日志
    logBusinessOperation('file_deleted', 'file', {
      fileId: file_id,
      filename,
      filePath
    }, req.user);
    
    res.json({
      success: true,
      message: '文件删除成功'
    });
  } catch (error) {
    if (error instanceof AppError) {
      throw error;
    }
    
    logError(error, {
      type: 'file_deletion_error',
      userId: req.user?.id,
      fileId: file_id
    });
    throw ErrorTypes.INTERNAL_ERROR('删除文件失败');
  }
});

/**
 * 批量删除文件
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 */
const batchDeleteFiles = catchAsync(async (req, res) => {
  const { file_ids } = req.body;
  
  if (!Array.isArray(file_ids) || file_ids.length === 0) {
    throw ErrorTypes.VALIDATION_ERROR('请提供要删除的文件ID列表');
  }
  
  if (file_ids.length > 50) {
    throw ErrorTypes.VALIDATION_ERROR('单次最多删除50个文件');
  }
  
  const results = {
    success: [],
    failed: []
  };
  
  for (const file_id of file_ids) {
    try {
      // 解码文件路径
      const filePath = Buffer.from(file_id, 'base64').toString();
      const filename = path.basename(filePath);
      
      if (fs.existsSync(filePath)) {
        const deleted = await deleteFile(filePath);
        
        if (deleted) {
          results.success.push({
            file_id,
            filename,
            message: '删除成功'
          });
        } else {
          results.failed.push({
            file_id,
            filename,
            message: '删除失败'
          });
        }
      } else {
        results.failed.push({
          file_id,
          filename: '未知',
          message: '文件不存在'
        });
      }
    } catch (error) {
      results.failed.push({
        file_id,
        filename: '未知',
        message: error.message || '删除失败'
      });
    }
  }
  
  // 记录操作日志
  logBusinessOperation('files_batch_deleted', 'file', {
    totalFiles: file_ids.length,
    successCount: results.success.length,
    failedCount: results.failed.length
  }, req.user);
  
  res.json({
    success: true,
    message: `批量删除完成，成功: ${results.success.length}，失败: ${results.failed.length}`,
    data: results
  });
});

/**
 * 获取文件统计信息
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 */
const getFileStatistics = catchAsync(async (req, res) => {
  const uploadDir = path.join(__dirname, '../../../uploads');
  
  try {
    const typeDirs = {
      avatar: path.join(uploadDir, 'avatars'),
      animal: path.join(uploadDir, 'animals'),
      travel: path.join(uploadDir, 'travels'),
      document: path.join(uploadDir, 'documents')
    };
    
    const stats = {
      totalFiles: 0,
      totalSize: 0,
      typeStats: [],
      sizeDistribution: {
        small: 0,    // < 1MB
        medium: 0,   // 1MB - 5MB
        large: 0     // > 5MB
      },
      formatStats: {}
    };
    
    for (const [type, dir] of Object.entries(typeDirs)) {
      if (!fs.existsSync(dir)) {
        stats.typeStats.push({
          type,
          count: 0,
          size: 0,
          avgSize: 0
        });
        continue;
      }
      
      const files = fs.readdirSync(dir);
      let typeCount = 0;
      let typeSize = 0;
      
      for (const file of files) {
        // 跳过缩略图文件
        if (file.includes('_thumb')) continue;
        
        const filePath = path.join(dir, file);
        const fileStat = fs.statSync(filePath);
        const fileSize = fileStat.size;
        const ext = path.extname(file).toLowerCase();
        
        typeCount++;
        typeSize += fileSize;
        stats.totalFiles++;
        stats.totalSize += fileSize;
        
        // 大小分布统计
        if (fileSize < 1024 * 1024) {
          stats.sizeDistribution.small++;
        } else if (fileSize < 5 * 1024 * 1024) {
          stats.sizeDistribution.medium++;
        } else {
          stats.sizeDistribution.large++;
        }
        
        // 格式统计
        if (!stats.formatStats[ext]) {
          stats.formatStats[ext] = { count: 0, size: 0 };
        }
        stats.formatStats[ext].count++;
        stats.formatStats[ext].size += fileSize;
      }
      
      stats.typeStats.push({
        type,
        count: typeCount,
        size: typeSize,
        avgSize: typeCount > 0 ? Math.round(typeSize / typeCount) : 0
      });
    }
    
    // 转换格式统计为数组
    const formatStatsArray = Object.entries(stats.formatStats).map(([format, data]) => ({
      format,
      count: data.count,
      size: data.size,
      percentage: ((data.count / stats.totalFiles) * 100).toFixed(2)
    })).sort((a, b) => b.count - a.count);
    
    stats.formatStats = formatStatsArray;
    
    // 记录操作日志
    logBusinessOperation('file_statistics_viewed', 'file', {
      totalFiles: stats.totalFiles,
      totalSize: stats.totalSize
    }, req.user);
    
    res.json({
      success: true,
      message: '获取成功',
      data: stats
    });
  } catch (error) {
    logError(error, {
      type: 'file_statistics_error',
      userId: req.user?.id
    });
    throw ErrorTypes.INTERNAL_ERROR('获取文件统计失败');
  }
});

/**
 * 清理无用文件
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 */
const cleanupUnusedFiles = catchAsync(async (req, res) => {
  const { dry_run = true } = req.query;
  
  try {
    const uploadDir = path.join(__dirname, '../../../uploads');
    const typeDirs = {
      avatar: path.join(uploadDir, 'avatars'),
      animal: path.join(uploadDir, 'animals'),
      travel: path.join(uploadDir, 'travels'),
      document: path.join(uploadDir, 'documents')
    };
    
    const results = {
      scanned: 0,
      unused: [],
      deleted: [],
      errors: []
    };
    
    // 这里应该根据实际业务逻辑检查文件是否被使用
    // 目前只是示例，检查30天前的文件
    const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
    
    for (const [type, dir] of Object.entries(typeDirs)) {
      if (!fs.existsSync(dir)) continue;
      
      const files = fs.readdirSync(dir);
      
      for (const file of files) {
        // 跳过缩略图文件
        if (file.includes('_thumb')) continue;
        
        const filePath = path.join(dir, file);
        const stats = fs.statSync(filePath);
        
        results.scanned++;
        
        // 检查文件是否超过30天且未被使用（这里需要根据实际业务逻辑实现）
        if (stats.mtime < thirtyDaysAgo) {
          results.unused.push({
            filename: file,
            type,
            size: stats.size,
            lastModified: stats.mtime
          });
          
          // 如果不是试运行，则删除文件
          if (dry_run !== 'true') {
            try {
              const deleted = await deleteFile(filePath);
              if (deleted) {
                results.deleted.push({
                  filename: file,
                  type,
                  size: stats.size
                });
              }
            } catch (error) {
              results.errors.push({
                filename: file,
                type,
                error: error.message
              });
            }
          }
        }
      }
    }
    
    // 记录操作日志
    logBusinessOperation('file_cleanup', 'file', {
      dryRun: dry_run === 'true',
      scanned: results.scanned,
      unused: results.unused.length,
      deleted: results.deleted.length,
      errors: results.errors.length
    }, req.user);
    
    res.json({
      success: true,
      message: dry_run === 'true' ? '扫描完成（试运行）' : '清理完成',
      data: results
    });
  } catch (error) {
    logError(error, {
      type: 'file_cleanup_error',
      userId: req.user?.id,
      dryRun: dry_run === 'true'
    });
    throw ErrorTypes.INTERNAL_ERROR('文件清理失败');
  }
});

/**
 * 上传文件
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 */
const uploadFile = catchAsync(async (req, res) => {
  if (!req.file && !req.files) {
    throw ErrorTypes.VALIDATION_ERROR('请选择要上传的文件');
  }
  
  const files = req.files || [req.file];
  const uploadedFiles = [];
  
  for (const file of files) {
    const fileInfo = {
      id: Buffer.from(file.path).toString('base64'),
      filename: file.filename,
      originalName: file.originalname,
      size: file.size,
      mimetype: file.mimetype,
      url: file.path.replace(path.join(__dirname, '../../../'), '/'),
      thumbnailUrl: file.thumbnail ? file.path.replace(path.basename(file.path), file.thumbnail).replace(path.join(__dirname, '../../../'), '/') : null,
      created_at: new Date()
    };
    
    uploadedFiles.push(fileInfo);
  }
  
  // 记录操作日志
  logBusinessOperation('files_uploaded', 'file', {
    fileCount: uploadedFiles.length,
    files: uploadedFiles.map(f => ({
      filename: f.filename,
      size: f.size,
      mimetype: f.mimetype
    }))
  }, req.user);
  
  res.json({
    success: true,
    message: '文件上传成功',
    data: {
      files: uploadedFiles
    }
  });
});

module.exports = {
  getFileList,
  getFileDetail,
  deleteFileById,
  batchDeleteFiles,
  getFileStatistics,
  cleanupUnusedFiles,
  uploadFile
};