// Server-only, in-memory sliding-window limiter — deliberately no Redis:
// this app runs as a single Coolify container, so a plain in-process Map
// is sufficient and needs zero new infra. Counters reset on redeploy/
// restart (acceptable — an attacker gets a few extra free attempts right
// after a deploy, not a meaningful window) and won't share state if this
// ever scales to multiple instances; revisit with a shared store then.
//
// Complements, doesn't replace, Payload's own built-in per-account login
// lockout (Customers collection, maxLoginAttempts: 5 / lockTime: 10min,
// Payload defaults) — that stops brute-forcing one account, this stops an
// IP hammering registration or spraying attempts across many accounts.
const attempts = new Map<string, number[]>();

// Prevents unbounded growth from IPs that hit a route once and never
// return — without this, `attempts` would grow forever on a low-traffic
// site that nonetheless gets scanned/crawled periodically.
const MAX_TRACKED_KEYS = 10_000;

export function checkRateLimit(key: string, { limit, windowMs }: { limit: number; windowMs: number }): boolean {
  const now = Date.now();
  const windowStart = now - windowMs;
  const timestamps = (attempts.get(key) ?? []).filter((t) => t > windowStart);

  if (timestamps.length >= limit) {
    attempts.set(key, timestamps);
    return false;
  }

  timestamps.push(now);
  if (attempts.size >= MAX_TRACKED_KEYS && !attempts.has(key)) {
    attempts.clear();
  }
  attempts.set(key, timestamps);
  return true;
}

// Caddy sits in front of this app and sets X-Forwarded-For — falls back to
// a constant key (effectively a single shared bucket) if that's ever
// missing, e.g. local dev, rather than disabling rate limiting outright.
export function getClientIp(request: Request): string {
  const forwarded = request.headers.get("x-forwarded-for");
  return forwarded?.split(",")[0]?.trim() || "unknown";
}
