/**
 * In-memory IP rate limiter for authentication endpoints.
 *
 * Configured for:
 *   - Max 5 failed attempts per 15-minute window per IP.
 *   - Automatically purges expired entries to prevent memory leaks.
 */

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

const store = new Map<string, RateLimitEntry>();

// Clean up expired entries every 5 minutes
if (typeof setInterval !== "undefined") {
  const cleanup = setInterval(() => {
    const now = Date.now();
    for (const [key, entry] of store.entries()) {
      if (now > entry.resetAt) {
        store.delete(key);
      }
    }
  }, 5 * 60 * 1000);

  // Don't keep Node event loop alive just for cleanup
  if (cleanup.unref) {
    cleanup.unref();
  }
}

export interface RateLimitResult {
  allowed: boolean;
  retryAfterSeconds?: number;
  remainingAttempts?: number;
}

/**
 * Check and increment the rate limit for a given identifier (e.g. IP address).
 *
 * @param identifier - Key to limit (typically client IP address)
 * @param maxAttempts - Maximum attempts allowed in window (default: 5)
 * @param windowMs - Time window in milliseconds (default: 15 minutes)
 */
export function checkRateLimit(
  identifier: string,
  maxAttempts: number = 5,
  windowMs: number = 15 * 60 * 1000
): RateLimitResult {
  const now = Date.now();
  const entry = store.get(identifier);

  if (!entry || now > entry.resetAt) {
    // New or expired window: allow and start fresh
    store.set(identifier, {
      count: 1,
      resetAt: now + windowMs,
    });
    return {
      allowed: true,
      remainingAttempts: maxAttempts - 1,
    };
  }

  // Active window
  if (entry.count >= maxAttempts) {
    const retryAfterSeconds = Math.max(1, Math.ceil((entry.resetAt - now) / 1000));
    return {
      allowed: false,
      retryAfterSeconds,
      remainingAttempts: 0,
    };
  }

  entry.count += 1;
  return {
    allowed: true,
    remainingAttempts: maxAttempts - entry.count,
  };
}

/**
 * Reset rate limit for an identifier (e.g. on successful login).
 */
export function resetRateLimit(identifier: string): void {
  store.delete(identifier);
}
