import { ApiError } from "../utils/ApiError.js";

const ipBuckets = new Map();

const pruneExpiredBuckets = (now) => {
  for (const [key, bucket] of ipBuckets.entries()) {
    if (bucket.expiresAt <= now) {
      ipBuckets.delete(key);
    }
  }
};

export const createRateLimit = ({
  key = "global",
  windowMs,
  max,
  message,
}) => {
  if (!windowMs || !max) {
    throw new Error("Rate limit requires windowMs and max.");
  }

  return (req, res, next) => {
    const now = Date.now();
    const bucketKey = `${key}:${req.ip}`;
    const existing = ipBuckets.get(bucketKey);

    pruneExpiredBuckets(now);

    if (!existing || existing.expiresAt <= now) {
      ipBuckets.set(bucketKey, {
        count: 1,
        expiresAt: now + windowMs,
      });

      return next();
    }

    if (existing.count >= max) {
      return next(
        new ApiError(
          429,
          message || "Trop de tentatives. Veuillez réessayer plus tard.",
        ),
      );
    }

    existing.count += 1;
    ipBuckets.set(bucketKey, existing);

    return next();
  };
};

export const authLoginRateLimit = createRateLimit({
  key: "auth-login",
  windowMs: 15 * 60 * 1000,
  max: 5,
  message:
    "Trop de tentatives de connexion depuis cette adresse IP. Réessayez dans 15 minutes.",
});
