import type { Request, Response, NextFunction } from "express";

interface RateLimitEntry {
  count: number;
  resetTime: number;
}

export const createRateLimiter = (options: { windowMs: number; max: number; message?: string }) => {
  const store = new Map<string, RateLimitEntry>();

  // Clean up expired entries every window cycle
  const cleanup = setInterval(() => {
    const now = Date.now();
    for (const [ip, record] of store.entries()) {
      if (record.resetTime < now) {
        store.delete(ip);
      }
    }
  }, options.windowMs);

  if (cleanup.unref) cleanup.unref();

  return (req: Request, res: Response, next: NextFunction): void => {
    const headerIp = req.headers["x-forwarded-for"];
    const rawIp = (Array.isArray(headerIp) ? headerIp[0] : headerIp) || req.socket?.remoteAddress || "unknown";
    const ip = rawIp.split(",")[0]?.trim() || "unknown";
    const now = Date.now();

    const currentRecord = store.get(ip);

    if (!currentRecord || currentRecord.resetTime < now) {
      store.set(ip, { count: 1, resetTime: now + options.windowMs });
      return next();
    }

    currentRecord.count += 1;

    if (currentRecord.count > options.max) {
      res.status(429).json({
        message: options.message || "Too many requests. Please try again later.",
      });
      return;
    }

    next();
  };
};

export const authRateLimiter = createRateLimiter({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 10, // 10 attempts per 15 mins
  message: "Too many login or OTP attempts from this IP. Please try again after 15 minutes.",
});
