/**
 * Rate limiting for Next.js API routes
 * Uses in-memory store (for production, use Redis)
 */

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

// In-memory store for rate limiting
const rateLimitStore = new Map<string, RateLimitEntry>();

// Cleanup old entries every 5 minutes
setInterval(() => {
  const now = Date.now();
  for (const [key, entry] of rateLimitStore.entries()) {
    if (entry.resetTime < now) {
      rateLimitStore.delete(key);
    }
  }
}, 5 * 60 * 1000);

interface RateLimitConfig {
  windowMs: number; // Time window in milliseconds
  max: number; // Max requests per window
  message: {
    error: string;
    message: string;
    retryAfter: number; // seconds
  };
  keyGenerator?: (request: Request) => string;
  skipSuccessfulRequests?: boolean;
}

/**
 * Creates a rate limiter middleware
 */
export function createRateLimiter(config: RateLimitConfig) {
  return async (request: Request): Promise<Response | null> => {
    const now = Date.now();
    const key = config.keyGenerator
      ? config.keyGenerator(request)
      : request.headers.get('x-forwarded-for') || 'unknown';

    const identifier = `${key}:${request.url}`;
    const entry = rateLimitStore.get(identifier);

    if (!entry || entry.resetTime < now) {
      // Create new entry
      rateLimitStore.set(identifier, {
        count: 1,
        resetTime: now + config.windowMs,
      });

      return null; // Allow request
    }

    if (entry.count >= config.max) {
      // Rate limit exceeded
      const retryAfter = Math.ceil((entry.resetTime - now) / 1000);

      return new Response(
        JSON.stringify({
          ...config.message,
          retryAfter,
        }),
        {
          status: 429,
          headers: {
            'Content-Type': 'application/json',
            'RateLimit-Limit': config.max.toString(),
            'RateLimit-Remaining': '0',
            'RateLimit-Reset': entry.resetTime.toString(),
            'Retry-After': retryAfter.toString(),
          },
        }
      );
    }

    // Increment count
    entry.count += 1;
    rateLimitStore.set(identifier, entry);

    return null; // Allow request
  };
}

/**
 * Strict rate limit for authentication endpoints (login, register, password reset)
 */
export const authLimiter = createRateLimiter({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 5, // 5 attempts per 15 minutes
  message: {
    error: 'AUTH_RATE_LIMIT_EXCEEDED',
    message: 'Too many authentication attempts. Please try again later.',
    retryAfter: 15 * 60,
  },
});

/**
 * Moderate rate limit for AI assistant endpoints
 */
export const aiLimiter = createRateLimiter({
  windowMs: 60 * 60 * 1000, // 1 hour
  max: 10, // 10 queries per hour
  message: {
    error: 'AI_RATE_LIMIT_EXCEEDED',
    message: 'You have reached your AI assistant query limit. Please try again later or upgrade to premium.',
    retryAfter: 60 * 60,
  },
  keyGenerator: (req) => {
    // TODO: Use user ID from session/token when available
    return req.headers.get('x-forwarded-for') || 'unknown';
  },
});

/**
 * General rate limit for tracking endpoints (feeding, sleep, etc.)
 */
export const trackingLimiter = createRateLimiter({
  windowMs: 1 * 60 * 1000, // 1 minute
  max: 30, // 30 requests per minute
  message: {
    error: 'TRACKING_RATE_LIMIT_EXCEEDED',
    message: 'Too many tracking requests. Please slow down.',
    retryAfter: 60,
  },
});

/**
 * Lenient rate limit for read-only endpoints (GET requests)
 */
export const readLimiter = createRateLimiter({
  windowMs: 1 * 60 * 1000, // 1 minute
  max: 100, // 100 requests per minute
  message: {
    error: 'READ_RATE_LIMIT_EXCEEDED',
    message: 'Too many requests. Please slow down.',
    retryAfter: 60,
  },
});

/**
 * Very strict rate limit for sensitive operations (delete account, etc.)
 */
export const sensitiveLimiter = createRateLimiter({
  windowMs: 60 * 60 * 1000, // 1 hour
  max: 3, // Only 3 sensitive operations per hour
  message: {
    error: 'SENSITIVE_RATE_LIMIT_EXCEEDED',
    message: 'Too many sensitive operations. Please try again later.',
    retryAfter: 60 * 60,
  },
});

/**
 * Helper to apply rate limiter to Next.js API routes
 *
 * Usage:
 * ```typescript
 * import { authLimiter } from '@/lib/middleware/rateLimiter';
 *
 * export async function POST(request: Request) {
 *   const rateLimitResult = await authLimiter(request);
 *   if (rateLimitResult) return rateLimitResult; // Return 429 response
 *
 *   // Continue with normal request handling
 * }
 * ```
 */
