const logger = require('../utils/logger');
const onFinished = require('on-finished');

// Middleware para loggear todas las requests
const requestLogger = (req, res, next) => {
  const startTime = Date.now();

  // Capturar información de la request
  const requestInfo = {
    method: req.method,
    url: req.originalUrl,
    ip: req.ip || req.connection.remoteAddress,
    userAgent: req.get('user-agent'),
    referer: req.get('referer'),
    userId: req.user ? req.user.id : null,
    userType: req.user ? req.user.type : null,
  };

  // Log de inicio de request (solo en debug)
  logger.debug(`Incoming request: ${req.method} ${req.originalUrl}`, {
    ...requestInfo,
    body: sanitizeBody(req.body),
    query: req.query,
  });

  // Cuando la respuesta termine
  onFinished(res, (err, res) => {
    const responseTime = Date.now() - startTime;
    const statusCode = res.statusCode;

    // Determinar el nivel de log según el status code
    let logLevel = 'info';
    if (statusCode >= 500) {
      logLevel = 'error';
    } else if (statusCode >= 400) {
      logLevel = 'warn';
    } else if (statusCode >= 300) {
      logLevel = 'info';
    }

    // Log de respuesta
    logger[logLevel](`${req.method} ${req.originalUrl} ${statusCode}`, {
      ...requestInfo,
      statusCode,
      responseTime: `${responseTime}ms`,
      contentLength: res.get('content-length'),
    });

    // Log especial para requests lentas (> 1 segundo)
    if (responseTime > 1000) {
      logger.warn(`Slow request detected: ${req.method} ${req.originalUrl}`, {
        ...requestInfo,
        responseTime: `${responseTime}ms`,
      });
    }

    // Log de errores
    if (err) {
      logger.error(`Request error: ${req.method} ${req.originalUrl}`, {
        ...requestInfo,
        error: err.message,
        stack: err.stack,
      });
    }
  });

  next();
};

// Sanitizar body para no loggear información sensible
const sanitizeBody = (body) => {
  if (!body || typeof body !== 'object') {
    return body;
  }

  const sensitiveFields = [
    'password',
    'Password',
    'token',
    'Token',
    'secret',
    'Secret',
    'apiKey',
    'ApiKey',
    'creditCard',
    'CreditCard',
    'ssn',
    'SSN',
  ];

  const sanitized = { ...body };

  sensitiveFields.forEach(field => {
    if (sanitized[field]) {
      sanitized[field] = '***REDACTED***';
    }
  });

  return sanitized;
};

// Middleware para loggear eventos de autenticación
const authLogger = (action) => {
  return (req, res, next) => {
    const originalJson = res.json.bind(res);

    res.json = function (data) {
      const success = data.success;
      const email = req.body.email || req.body.Email;
      const ip = req.ip || req.connection.remoteAddress;

      if (success) {
        logger.auth(`${action} exitoso`, {
          email,
          ip,
          userAgent: req.get('user-agent'),
          userType: req.userType,
        });
      } else {
        logger.security(`${action} fallido`, {
          email,
          ip,
          userAgent: req.get('user-agent'),
          reason: data.message,
        });
      }

      return originalJson(data);
    };

    next();
  };
};

// Middleware para loggear operaciones CRUD
const crudLogger = (action, resource) => {
  return (req, res, next) => {
    const originalJson = res.json.bind(res);

    res.json = function (data) {
      if (data.success) {
        logger.audit(action, req.user?.id, resource, {
          resourceId: req.params.id || data.data?.Id,
          ip: req.ip,
          userType: req.user?.type,
        });
      }

      return originalJson(data);
    };

    next();
  };
};

// Middleware para loggear accesos a datos sensibles
const sensitiveDataLogger = (dataType) => {
  return (req, res, next) => {
    logger.security(`Acceso a datos sensibles: ${dataType}`, {
      userId: req.user?.id,
      userType: req.user?.type,
      ip: req.ip,
      url: req.originalUrl,
      method: req.method,
    });

    next();
  };
};

module.exports = {
  requestLogger,
  authLogger,
  crudLogger,
  sensitiveDataLogger,
};