/**
 * Simple in-memory rate limiting utility.
 * 
 * Uses a sliding window approach with cleanup of expired entries.
 * For production, use Redis or a proper rate limiting service.
 */

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

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

// Clean up expired entries every 10 minutes
if (typeof globalThis !== 'undefined') {
  setInterval(() => {
    const now = Date.now();
    for (const [key, entry] of rateLimitStore.entries()) {
      if (now > entry.resetTime) {
        rateLimitStore.delete(key);
      }
    }
  }, 10 * 60 * 1000);
}

export interface RateLimitConfig {
  /** Maximum number of requests allowed in the window */
  maxRequests: number;
  /** Time window in milliseconds */
  windowMs: number;
}

// Predefined rate limit configurations
export const RATE_LIMITS = {
  /** Strict limit for auth endpoints (5 requests per minute) */
  auth: { maxRequests: 5, windowMs: 60 * 1000 },
  /** Standard limit for API endpoints (30 requests per minute) */
  api: { maxRequests: 30, windowMs: 60 * 1000 },
  /** Lenient limit for read endpoints (60 requests per minute) */
  read: { maxRequests: 60, windowMs: 60 * 1000 },
  /** Strict limit for admin write operations (20 requests per minute) */
  adminWrite: { maxRequests: 20, windowMs: 60 * 1000 },
} as const;

/**
 * Check if a request should be rate limited.
 * Returns true if the request should be allowed, false if it should be blocked.
 */
export function checkRateLimit(
  identifier: string,
  config: RateLimitConfig = RATE_LIMITS.api
): { allowed: boolean; remaining: number; resetTime: number } {
  const now = Date.now();
  const entry = rateLimitStore.get(identifier);

  if (!entry || now > entry.resetTime) {
    // No entry or expired - create new
    const newEntry: RateLimitEntry = {
      count: 1,
      resetTime: now + config.windowMs,
    };
    rateLimitStore.set(identifier, newEntry);
    return {
      allowed: true,
      remaining: config.maxRequests - 1,
      resetTime: newEntry.resetTime,
    };
  }

  if (entry.count >= config.maxRequests) {
    return {
      allowed: false,
      remaining: 0,
      resetTime: entry.resetTime,
    };
  }

  entry.count++;
  return {
    allowed: true,
    remaining: config.maxRequests - entry.count,
    resetTime: entry.resetTime,
  };
}

/**
 * Get a rate limit identifier from a request.
 * Uses IP address from headers or falls back to a default.
 */
export function getRateLimitIdentifier(request: Request): string {
  // Try to get the real IP from common headers
  const forwarded = request.headers.get('x-forwarded-for');
  const realIp = request.headers.get('x-real-ip');
  
  if (forwarded) {
    return `ip:${forwarded.split(',')[0].trim()}`;
  }
  if (realIp) {
    return `ip:${realIp.trim()}`;
  }
  
  // Fallback - use a combination of user agent and other headers
  const userAgent = request.headers.get('user-agent') || 'unknown';
  return `ua:${userAgent.slice(0, 50)}`;
}

/**
 * Create a rate limit error response.
 */
export function rateLimitError(resetTime: number) {
  return Response.json(
    { success: false, error: 'Too many requests. Please try again later.' },
    { 
      status: 429,
      headers: {
        'Retry-After': String(Math.ceil((resetTime - Date.now()) / 1000)),
      }
    }
  );
}
