/**
 * 操作日志中间件
 * @file operationLogger.js
 * @description 自动记录用户操作的中间件
 */
const { OperationLog } = require('../models');

/**
 * 操作日志中间件
 * @param {Object} options 配置选项
 * @param {string} options.moduleName 模块名称
 * @param {string} options.tableName 数据表名
 * @param {Function} options.getRecordId 获取记录ID的函数
 * @param {Function} options.getOperationDesc 获取操作描述的函数
 * @param {Function} options.getOldData 获取操作前数据的函数（可选）
 * @param {Function} options.getNewData 获取操作后数据的函数（可选）
 * @returns {Function} 中间件函数
 */
const operationLogger = (options = {}) => {
  const {
    moduleName,
    tableName,
    getRecordId = () => null,
    getOperationDesc = () => '未知操作',
    getOldData = () => null,
    getNewData = () => null
  } = options;

  return async (req, res, next) => {
    const startTime = Date.now();
    const originalSend = res.send;
    let responseBody = null;

    // 拦截响应数据
    res.send = function(data) {
      responseBody = data;
      return originalSend.call(this, data);
    };

    // 在响应完成后记录日志
    res.on('finish', async () => {
      try {
        const executionTime = Date.now() - startTime;
        const operationType = getOperationType(req.method);
        
        if (!operationType) {
          return; // 只记录增删改操作
        }

        const recordId = getRecordId(req, res);
        const operationDesc = getOperationDesc(req, res);
        const oldData = getOldData(req, res);
        const newData = getNewData(req, res);

        // 获取用户信息
        const user = req.user;
        if (!user) {
          return; // 没有用户信息不记录日志
        }

        // 获取IP地址
        const ipAddress = req.ip || 
          req.connection.remoteAddress || 
          req.socket.remoteAddress ||
          (req.connection.socket ? req.connection.socket.remoteAddress : null) ||
          req.headers['x-forwarded-for']?.split(',')[0]?.trim() ||
          'unknown';

        // 记录操作日志
        await OperationLog.recordOperation({
          userId: user.id,
          username: user.username,
          userRole: user.roles,
          operationType,
          moduleName,
          tableName,
          recordId,
          operationDesc,
          oldData,
          newData,
          ipAddress,
          userAgent: req.get('User-Agent'),
          requestUrl: req.originalUrl,
          requestMethod: req.method,
          responseStatus: res.statusCode,
          executionTime,
          errorMessage: res.statusCode >= 400 ? responseBody?.message || '操作失败' : null
        });
      } catch (error) {
        console.error('记录操作日志失败:', error);
        // 不抛出错误，避免影响主业务
      }
    });

    next();
  };
};

/**
 * 根据HTTP方法获取操作类型
 * @param {string} method HTTP方法
 * @returns {string|null} 操作类型
 */
const getOperationType = (method) => {
  switch (method.toUpperCase()) {
    case 'POST':
      return 'CREATE';
    case 'PUT':
    case 'PATCH':
      return 'UPDATE';
    case 'DELETE':
      return 'DELETE';
    default:
      return null;
  }
};

/**
 * 创建操作日志记录器
 * @param {Object} options 配置选项
 * @returns {Function} 中间件函数
 */
const createOperationLogger = (options) => {
  return operationLogger(options);
};

/**
 * 批量操作日志记录器
 * @param {Array} operations 操作配置数组
 * @returns {Function} 中间件函数
 */
const createBatchOperationLogger = (operations) => {
  return async (req, res, next) => {
    const startTime = Date.now();
    const originalSend = res.send;
    let responseBody = null;

    // 拦截响应数据
    res.send = function(data) {
      responseBody = data;
      return originalSend.call(this, data);
    };

    // 在响应完成后记录日志
    res.on('finish', async () => {
      try {
        const executionTime = Date.now() - startTime;
        const operationType = getOperationType(req.method);
        
        if (!operationType) {
          return;
        }

        const user = req.user;
        if (!user) {
          return;
        }

        const ipAddress = req.ip || 
          req.connection.remoteAddress || 
          req.socket.remoteAddress ||
          (req.connection.socket ? req.connection.socket.remoteAddress : null) ||
          req.headers['x-forwarded-for']?.split(',')[0]?.trim() ||
          'unknown';

        // 为每个操作配置记录日志
        for (const operation of operations) {
          const {
            moduleName,
            tableName,
            getRecordId = () => null,
            getOperationDesc = () => '未知操作',
            getOldData = () => null,
            getNewData = () => null
          } = operation;

          const recordId = getRecordId(req, res);
          const operationDesc = getOperationDesc(req, res);
          const oldData = getOldData(req, res);
          const newData = getNewData(req, res);

          await OperationLog.recordOperation({
            userId: user.id,
            username: user.username,
            userRole: user.roles,
            operationType,
            moduleName,
            tableName,
            recordId,
            operationDesc,
            oldData,
            newData,
            ipAddress,
            userAgent: req.get('User-Agent'),
            requestUrl: req.originalUrl,
            requestMethod: req.method,
            responseStatus: res.statusCode,
            executionTime,
            errorMessage: res.statusCode >= 400 ? responseBody?.message || '操作失败' : null
          });
        }
      } catch (error) {
        console.error('记录批量操作日志失败:', error);
      }
    });

    next();
  };
};

module.exports = {
  operationLogger,
  createOperationLogger,
  createBatchOperationLogger,
  getOperationType
};
