/**
 * Simple in-memory rate limiter (Map-based).
 * Good enough for single-instance deployments.
 * For multi-instance, swap to Redis-backed implementation.
 */

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

interface RateLimitResult {
  allowed: boolean;
  remaining: number;
  resetAt: Date;
}

export interface RateLimiter {
  (key: string): RateLimitResult;
  reset(): void;
}

/**
 * Creates a sliding-window rate limiter.
 * @param windowMs  - Time window in milliseconds
 * @param maxRequests - Maximum requests allowed within the window
 */
export function createRateLimiter(windowMs: number, maxRequests: number): RateLimiter {
  const store = new Map<string, RateLimitEntry>();

  // Periodically clean up expired entries to prevent memory leaks
  const cleanupInterval = setInterval(() => {
    const now = Date.now();
    for (const [key, entry] of store) {
      if (entry.resetAt <= now) {
        store.delete(key);
      }
    }
  }, windowMs);

  // Allow garbage collection if the process holds no other references
  if (cleanupInterval.unref) {
    cleanupInterval.unref();
  }

  const check = function check(key: string): RateLimitResult {
    const now = Date.now();
    const existing = store.get(key);

    // Window expired or first request — start fresh
    if (!existing || existing.resetAt <= now) {
      const resetAt = now + windowMs;
      store.set(key, { count: 1, resetAt });
      return {
        allowed: true,
        remaining: maxRequests - 1,
        resetAt: new Date(resetAt),
      };
    }

    // Within the current window
    existing.count += 1;
    const allowed = existing.count <= maxRequests;
    return {
      allowed,
      remaining: Math.max(0, maxRequests - existing.count),
      resetAt: new Date(existing.resetAt),
    };
  } as RateLimiter;

  check.reset = () => {
    store.clear();
  };

  return check;
}

/** General API rate limiter: 100 requests per 15 minutes per key */
export const apiRateLimiter = createRateLimiter(15 * 60 * 1000, 100);

/** Auth rate limiter: 5 attempts per 15 minutes per key */
export const authRateLimiter = createRateLimiter(15 * 60 * 1000, 5);
