import { NextResponse } from "next/server";

interface RateLimitStore {
  [key: string]: {
    count: number;
    resetTime: number;
  };
}

const store: RateLimitStore = {};

interface RateLimitConfig {
  interval: number; // Time window in milliseconds
  maxRequests: number; // Maximum requests in time window
}

/**
 * Simple in-memory rate limiter
 * For production, use Redis or a dedicated rate limiting service
 *
 * @param identifier - Unique identifier (e.g., IP address, user ID)
 * @param config - Rate limit configuration
 * @returns NextResponse error if rate limited, undefined if allowed
 *
 * @example
 * const rateLimitError = rateLimit(userId, { interval: 60000, maxRequests: 5 });
 * if (rateLimitError) return rateLimitError;
 */
export function rateLimit(
  identifier: string,
  config: RateLimitConfig,
): NextResponse | undefined {
  const now = Date.now();
  const key = identifier;

  // Initialize or reset if window expired
  if (!store[key] || now > store[key].resetTime) {
    store[key] = {
      count: 1,
      resetTime: now + config.interval,
    };
    return undefined;
  }

  // Increment count
  store[key].count++;

  // Check if limit exceeded
  if (store[key].count > config.maxRequests) {
    const retryAfter = Math.ceil((store[key].resetTime - now) / 1000);

    return NextResponse.json(
      {
        error: "Too many requests",
        message: `Rate limit exceeded. Try again in ${retryAfter} seconds.`,
        retryAfter,
      },
      {
        status: 429,
        headers: {
          "Retry-After": retryAfter.toString(),
          "X-RateLimit-Limit": config.maxRequests.toString(),
          "X-RateLimit-Remaining": "0",
          "X-RateLimit-Reset": store[key].resetTime.toString(),
        },
      },
    );
  }

  return undefined;
}

/**
 * Rate limit configurations for different endpoints
 */
export const RATE_LIMITS = {
  // Authentication endpoints - stricter limits
  login: { interval: 60000, maxRequests: 5 }, // 5 attempts per minute
  register: { interval: 3600000, maxRequests: 3 }, // 3 attempts per hour
  passwordReset: { interval: 3600000, maxRequests: 3 }, // 3 attempts per hour

  // API endpoints - more lenient
  api: { interval: 60000, maxRequests: 100 }, // 100 requests per minute
  apiStrict: { interval: 60000, maxRequests: 10 }, // 10 requests per minute
} as const;

/**
 * Get client identifier for rate limiting
 * Uses IP address as fallback if user is not authenticated
 *
 * @param request - NextRequest object
 * @param userId - Optional authenticated user ID
 * @returns Identifier for rate limiting
 */
export function getClientIdentifier(request: Request, userId?: string): string {
  if (userId) return `user:${userId}`;

  // Try to get IP from headers (works with most reverse proxies)
  const forwarded = request.headers.get("x-forwarded-for");
  const ip =
    forwarded?.split(",")[0] ?? request.headers.get("x-real-ip") ?? "unknown";

  return `ip:${ip}`;
}

/**
 * Cleanup expired rate limit entries (call periodically)
 */
export function cleanupRateLimitStore(): void {
  const now = Date.now();
  for (const key in store) {
    if (store[key].resetTime < now) {
      delete store[key];
    }
  }
}

// Cleanup every 10 minutes
if (typeof setInterval !== "undefined") {
  setInterval(cleanupRateLimitStore, 10 * 60 * 1000);
}
