import { Ratelimit } from '@upstash/ratelimit'
import { Redis } from '@upstash/redis'

// In-memory fallback for rate limiting when Redis is unavailable
class InMemoryRateLimiter {
  private cache: Map<string, { count: number; resetTime: number }> = new Map()
  private readonly maxLimit: number
  private readonly windowMs: number

  constructor(limit: number, windowMs: number) {
    this.maxLimit = limit
    this.windowMs = windowMs
  }

  async limit(identifier: string) {
    const now = Date.now()
    const entry = this.cache.get(identifier)

    // Clean up expired entries periodically
    if (Math.random() < 0.01) {
      for (const [key, value] of this.cache.entries()) {
        if (value.resetTime < now) {
          this.cache.delete(key)
        }
      }
    }

    if (!entry || entry.resetTime < now) {
      // New window
      const resetTime = now + this.windowMs
      this.cache.set(identifier, { count: 1, resetTime })
      return {
        success: true,
        limit: this.maxLimit,
        remaining: this.maxLimit - 1,
        reset: resetTime,
      }
    }

    if (entry.count >= this.maxLimit) {
      // Limit exceeded
      return {
        success: false,
        limit: this.maxLimit,
        remaining: 0,
        reset: entry.resetTime,
      }
    }

    // Increment count
    entry.count++
    return {
      success: true,
      limit: this.maxLimit,
      remaining: this.maxLimit - entry.count,
      reset: entry.resetTime,
    }
  }
}

// Force in-memory rate limiter to avoid Redis connection issues
// This ensures the app works without requiring Redis configuration
const redis = null;

// Rate limiter for expensive AI operations (transform/generate)
// 5 requests per hour per IP
export const aiRatelimit = new InMemoryRateLimiter(5, 60 * 60 * 1000) // 5 requests per hour

// Rate limiter for gallery submissions
// 10 requests per hour per IP
export const galleryRatelimit = new InMemoryRateLimiter(10, 60 * 60 * 1000) // 10 requests per hour

// Helper to get client IP from request
export function getClientIp(request: Request): string {
  const forwarded = request.headers.get('x-forwarded-for')
  const ip = forwarded ? forwarded.split(',')[0].trim() : 'anonymous'
  return ip
}

// Check rate limit and return error response if exceeded
export async function checkRateLimit(
  ratelimit: Ratelimit | InMemoryRateLimiter,
  identifier: string
): Promise<{ success: boolean; error?: Response }> {
  const { success, limit, reset, remaining } = await ratelimit.limit(identifier)

  if (!success) {
    const retryAfter = Math.ceil((reset - Date.now()) / 1000)
    return {
      success: false,
      error: new Response(
        JSON.stringify({
          error: 'Too many requests. Please try again later.',
          retryAfter,
        }),
        {
          status: 429,
          headers: {
            'Content-Type': 'application/json',
            'X-RateLimit-Limit': limit.toString(),
            'X-RateLimit-Remaining': remaining.toString(),
            'X-RateLimit-Reset': reset.toString(),
            'Retry-After': retryAfter.toString(),
          },
        }
      ),
    }
  }

  return { success: true }
}
