/**
 * 日志工具模块
 * 提供统一的日志记录功能，支持不同级别的日志输出
 */

const winston = require('winston');
const path = require('path');
const fs = require('fs');

// 确保日志目录存在
const logDir = path.join(__dirname, '../../logs');
if (!fs.existsSync(logDir)) {
  fs.mkdirSync(logDir, { recursive: true });
}

/**
 * 自定义日志格式
 */
const logFormat = winston.format.combine(
  winston.format.timestamp({
    format: 'YYYY-MM-DD HH:mm:ss'
  }),
  winston.format.errors({ stack: true }),
  winston.format.json(),
  winston.format.printf(({ timestamp, level, message, ...meta }) => {
    let logMessage = `${timestamp} [${level.toUpperCase()}]: ${message}`;
    
    // 如果有额外的元数据，添加到日志中
    if (Object.keys(meta).length > 0) {
      logMessage += `\n${JSON.stringify(meta, null, 2)}`;
    }
    
    return logMessage;
  })
);

/**
 * 创建Winston日志器
 */
const logger = winston.createLogger({
  level: process.env.LOG_LEVEL || 'info',
  format: logFormat,
  defaultMeta: { service: 'jiebanke-api' },
  transports: [
    // 错误日志文件
    new winston.transports.File({
      filename: path.join(logDir, 'error.log'),
      level: 'error',
      maxsize: 5242880, // 5MB
      maxFiles: 5,
      format: winston.format.combine(
        winston.format.timestamp(),
        winston.format.json()
      )
    }),
    
    // 组合日志文件
    new winston.transports.File({
      filename: path.join(logDir, 'combined.log'),
      maxsize: 5242880, // 5MB
      maxFiles: 5,
      format: winston.format.combine(
        winston.format.timestamp(),
        winston.format.json()
      )
    }),
    
    // 访问日志文件
    new winston.transports.File({
      filename: path.join(logDir, 'access.log'),
      level: 'http',
      maxsize: 5242880, // 5MB
      maxFiles: 5,
      format: winston.format.combine(
        winston.format.timestamp(),
        winston.format.json()
      )
    })
  ]
});

// 开发环境下添加控制台输出
if (process.env.NODE_ENV !== 'production') {
  logger.add(new winston.transports.Console({
    format: winston.format.combine(
      winston.format.colorize(),
      winston.format.simple(),
      winston.format.printf(({ timestamp, level, message, ...meta }) => {
        let logMessage = `${timestamp} [${level}]: ${message}`;
        
        // 如果有额外的元数据，添加到日志中
        if (Object.keys(meta).length > 0) {
          logMessage += `\n${JSON.stringify(meta, null, 2)}`;
        }
        
        return logMessage;
      })
    )
  }));
}

/**
 * 请求日志中间件
 * @param {Object} req - 请求对象
 * @param {Object} res - 响应对象
 * @param {Function} next - 下一个中间件
 */
const requestLogger = (req, res, next) => {
  const start = Date.now();
  
  // 记录请求开始
  logger.http('Request started', {
    method: req.method,
    url: req.originalUrl,
    ip: req.ip,
    userAgent: req.get('User-Agent'),
    userId: req.user?.id,
    timestamp: new Date().toISOString()
  });
  
  // 监听响应结束
  res.on('finish', () => {
    const duration = Date.now() - start;
    const logLevel = res.statusCode >= 400 ? 'warn' : 'http';
    
    logger.log(logLevel, 'Request completed', {
      method: req.method,
      url: req.originalUrl,
      statusCode: res.statusCode,
      duration: `${duration}ms`,
      ip: req.ip,
      userAgent: req.get('User-Agent'),
      userId: req.user?.id,
      timestamp: new Date().toISOString()
    });
  });
  
  next();
};

/**
 * 数据库操作日志
 * @param {string} operation - 操作类型
 * @param {string} table - 表名
 * @param {Object} data - 操作数据
 * @param {Object} user - 操作用户
 */
const logDatabaseOperation = (operation, table, data = {}, user = null) => {
  logger.info('Database operation', {
    operation,
    table,
    data: JSON.stringify(data),
    userId: user?.id,
    userType: user?.user_type,
    timestamp: new Date().toISOString()
  });
};

/**
 * 业务操作日志
 * @param {string} action - 操作动作
 * @param {string} resource - 资源类型
 * @param {Object} details - 操作详情
 * @param {Object} user - 操作用户
 */
const logBusinessOperation = (action, resource, details = {}, user = null) => {
  logger.info('Business operation', {
    action,
    resource,
    details: JSON.stringify(details),
    userId: user?.id,
    userType: user?.user_type,
    timestamp: new Date().toISOString()
  });
};

/**
 * 安全事件日志
 * @param {string} event - 事件类型
 * @param {Object} details - 事件详情
 * @param {Object} req - 请求对象
 */
const logSecurityEvent = (event, details = {}, req = null) => {
  logger.warn('Security event', {
    event,
    details: JSON.stringify(details),
    ip: req?.ip,
    userAgent: req?.get('User-Agent'),
    userId: req?.user?.id,
    timestamp: new Date().toISOString()
  });
};

/**
 * 性能监控日志
 * @param {string} operation - 操作名称
 * @param {number} duration - 执行时间（毫秒）
 * @param {Object} metadata - 额外元数据
 */
const logPerformance = (operation, duration, metadata = {}) => {
  const level = duration > 1000 ? 'warn' : 'info';
  
  logger.log(level, 'Performance monitoring', {
    operation,
    duration: `${duration}ms`,
    ...metadata,
    timestamp: new Date().toISOString()
  });
};

/**
 * 系统事件日志
 * @param {string} event - 事件类型
 * @param {Object} details - 事件详情
 */
const logSystemEvent = (event, details = {}) => {
  logger.info('System event', {
    event,
    details: JSON.stringify(details),
    timestamp: new Date().toISOString()
  });
};

/**
 * 错误日志（带上下文）
 * @param {Error} error - 错误对象
 * @param {Object} context - 错误上下文
 */
const logError = (error, context = {}) => {
  logger.error('Application error', {
    message: error.message,
    stack: error.stack,
    context: JSON.stringify(context),
    timestamp: new Date().toISOString()
  });
};

/**
 * 调试日志
 * @param {string} message - 调试信息
 * @param {Object} data - 调试数据
 */
const logDebug = (message, data = {}) => {
  if (process.env.NODE_ENV === 'development') {
    logger.debug(message, {
      data: JSON.stringify(data),
      timestamp: new Date().toISOString()
    });
  }
};

/**
 * 日志清理任务
 * 定期清理过期的日志文件
 */
const cleanupLogs = () => {
  const maxAge = 30 * 24 * 60 * 60 * 1000; // 30天
  const now = Date.now();
  
  fs.readdir(logDir, (err, files) => {
    if (err) {
      logger.error('Failed to read log directory', { error: err.message });
      return;
    }
    
    files.forEach(file => {
      const filePath = path.join(logDir, file);
      fs.stat(filePath, (err, stats) => {
        if (err) return;
        
        if (now - stats.mtime.getTime() > maxAge) {
          fs.unlink(filePath, (err) => {
            if (err) {
              logger.error('Failed to delete old log file', { 
                file: filePath, 
                error: err.message 
              });
            } else {
              logger.info('Deleted old log file', { file: filePath });
            }
          });
        }
      });
    });
  });
};

// 每天执行一次日志清理
setInterval(cleanupLogs, 24 * 60 * 60 * 1000);

/**
 * 日志统计信息
 */
const getLogStats = () => {
  return new Promise((resolve, reject) => {
    fs.readdir(logDir, (err, files) => {
      if (err) {
        reject(err);
        return;
      }
      
      const stats = {
        totalFiles: files.length,
        files: []
      };
      
      let processed = 0;
      
      files.forEach(file => {
        const filePath = path.join(logDir, file);
        fs.stat(filePath, (err, fileStat) => {
          if (!err) {
            stats.files.push({
              name: file,
              size: fileStat.size,
              created: fileStat.birthtime,
              modified: fileStat.mtime
            });
          }
          
          processed++;
          if (processed === files.length) {
            resolve(stats);
          }
        });
      });
      
      if (files.length === 0) {
        resolve(stats);
      }
    });
  });
};

module.exports = {
  logger,
  requestLogger,
  logDatabaseOperation,
  logBusinessOperation,
  logSecurityEvent,
  logPerformance,
  logSystemEvent,
  logError,
  logDebug,
  cleanupLogs,
  getLogStats
};