/**
 * Rate Limiting Middleware
 * Implements rate limiting for API endpoints
 */

import { FastifyRequest, FastifyReply } from 'fastify'

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

const store: RateLimitStore = {}

const RATE_LIMIT_WINDOW = 60 * 1000 // 1 minute
const RATE_LIMIT_MAX_REQUESTS = 100 // 100 requests per minute

/**
 * Get client identifier from request
 */
function getClientId(request: FastifyRequest): string {
  // Use IP address or user ID
  const ip = request.ip || request.socket.remoteAddress || 'unknown'
  const userId = (request as any).user?.id
  
  return userId ? `user:${userId}` : `ip:${ip}`
}

/**
 * Rate limiting middleware
 */
export async function rateLimitMiddleware(
  request: FastifyRequest,
  reply: FastifyReply
): Promise<void> {
  const clientId = getClientId(request)
  const now = Date.now()

  // Clean up expired entries
  Object.keys(store).forEach((key) => {
    if (store[key].resetTime < now) {
      delete store[key]
    }
  })

  // Get or create rate limit entry
  let entry = store[clientId]

  if (!entry || entry.resetTime < now) {
    entry = {
      count: 0,
      resetTime: now + RATE_LIMIT_WINDOW,
    }
    store[clientId] = entry
  }

  // Increment count
  entry.count++

  // Check if limit exceeded
  if (entry.count > RATE_LIMIT_MAX_REQUESTS) {
    reply.code(429).send({
      error: 'Too Many Requests',
      message: 'Rate limit exceeded. Please try again later.',
      retryAfter: Math.ceil((entry.resetTime - now) / 1000),
    })
    return
  }

  // Add rate limit headers
  reply.header('X-RateLimit-Limit', RATE_LIMIT_MAX_REQUESTS.toString())
  reply.header('X-RateLimit-Remaining', Math.max(0, RATE_LIMIT_MAX_REQUESTS - entry.count).toString())
  reply.header('X-RateLimit-Reset', entry.resetTime.toString())
}

