const rateLimit = require("express-rate-limit");
const logger = require("./logger");
const { RATE_LIMITS, HTTP_STATUS } = require("./constants");

const createRateLimiter = (config, limitType = "API") => {
  return rateLimit({
    windowMs: config.windowMs,
    max: config.max,
    skipSuccessfulRequests: config.skipSuccessfulRequests || false,
    skipFailedRequests: config.skipFailedRequests || false,
    message: {
      success: false,
      message: config.message,
    },
    standardHeaders: true,
    legacyHeaders: false,
    // Use X-Forwarded-For header from nginx/proxy - properly handle IPv6
    keyGenerator: (req, res) => {
      const ip =
        req.headers["x-forwarded-for"]?.split(",")[0]?.trim() ||
        req.headers["x-real-ip"] ||
        req.ip ||
        req.connection.remoteAddress;
      // Normalize IPv6 addresses to prevent bypass
      return ip.includes(":") ? ip.replace(/:/g, "-") : ip;
    },
    handler: (req, res) => {
      const clientIp =
        req.headers["x-forwarded-for"]?.split(",")[0]?.trim() || req.ip;
      logger.warn(`${limitType} rate limit exceeded`, {
        ip: clientIp,
        path: req.path,
        email: req.body?.email,
      });
      res.status(HTTP_STATUS.TOO_MANY_REQUESTS).json({
        success: false,
        message: config.message,
      });
    },
  });
};

// General API rate limiter
const apiLimiter = createRateLimiter(
  {
    windowMs:
      parseInt(process.env.RATE_LIMIT_WINDOW_MS) || RATE_LIMITS.API.windowMs,
    max: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS) || RATE_LIMITS.API.max,
    message: "Too many requests from this IP, please try again later.",
  },
  "API",
);

// Strict limiter for authentication endpoints
const authLimiter = createRateLimiter(
  {
    windowMs: RATE_LIMITS.AUTH.windowMs,
    max: RATE_LIMITS.AUTH.max,
    skipSuccessfulRequests: true,
    message: "Too many login attempts, please try again after 15 minutes.",
  },
  "Auth",
);

// File upload limiter
const uploadLimiter = createRateLimiter(
  {
    windowMs: RATE_LIMITS.UPLOAD.windowMs,
    max: RATE_LIMITS.UPLOAD.max,
    message: "Upload limit reached, please try again later.",
  },
  "Upload",
);

module.exports = {
  apiLimiter,
  authLimiter,
  uploadLimiter,
};
