/**
 * Rate Limiting Middleware
 * Prevents abuse by limiting requests per IP/user
 */

import { RateLimitError } from './errorHandler.mjs'
import { isAdmin } from '../config/index.mjs'

// In-memory store for rate limiting (use Redis in production)
const requestCounts = new Map()

// Clean up old entries every minute
setInterval(() => {
  const now = Date.now()
  for (const [key, data] of requestCounts.entries()) {
    if (now - data.windowStart > data.windowMs) {
      requestCounts.delete(key)
    }
  }
}, 60000)

/**
 * Create rate limiter middleware
 * @param {Object} options - Rate limit options
 * @param {number} options.windowMs - Time window in milliseconds
 * @param {number} options.max - Max requests per window
 * @param {string} options.message - Error message
 * @param {Function} options.keyGenerator - Function to generate unique key
 * @param {Function} options.skip - If (req) => true, do not count this request
 */
export function rateLimit(options = {}) {
  const {
    windowMs = 60000, // 1 minute
    max = 100,
    message = 'Zu viele Anfragen. Bitte versuche es später erneut.',
    keyGenerator = (req) => req.ip,
    skip = () => false,
  } = options

  return (req, res, next) => {
    if (skip(req)) {
      return next()
    }

    const key = keyGenerator(req)
    const now = Date.now()

    let data = requestCounts.get(key)

    if (!data || now - data.windowStart > windowMs) {
      data = { count: 0, windowStart: now, windowMs }
      requestCounts.set(key, data)
    }

    data.count++

    // Set rate limit headers
    res.set({
      'X-RateLimit-Limit': max,
      'X-RateLimit-Remaining': Math.max(0, max - data.count),
      'X-RateLimit-Reset': new Date(data.windowStart + windowMs).toISOString(),
    })

    if (data.count > max) {
      return next(new RateLimitError(message))
    }

    next()
  }
}

/**
 * Pre-configured rate limiters
 */
export const limiters = {
  // General API rate limit
  api: rateLimit({
    windowMs: 60000,
    max: 100,
    message: 'API Rate Limit überschritten',
  }),

  // Stricter limit for auth endpoints
  auth: rateLimit({
    windowMs: 900000, // 15 minutes
    max: 10,
    message: 'Zu viele Anmeldeversuche. Bitte warte 15 Minuten.',
  }),

  // Limit for email sorting (expensive operation); ADMIN_EMAILS (isAdmin) bypass
  emailSort: rateLimit({
    windowMs: 60000,
    max: 30, // Erhöht für Entwicklung
    message: 'E-Mail-Sortierung ist limitiert. Bitte warte eine Minute.',
    skip: (req) => isAdmin(req.appwriteUser?.email),
  }),

  // Limit for AI operations
  ai: rateLimit({
    windowMs: 60000,
    max: 20,
    message: 'KI-Anfragen sind limitiert.',
  }),
}
