/**
 * Rate Limiting Middleware Tests
 */

import { describe, it, expect, beforeEach, vi } from 'vitest'
import { rateLimitMiddleware } from '../rate-limit'
import type { FastifyRequest, FastifyReply } from 'fastify'

describe('Rate Limiting Middleware', () => {
  let mockRequest: Partial<FastifyRequest>
  let mockReply: Partial<FastifyReply>

  beforeEach(() => {
    mockRequest = {
      ip: '127.0.0.1',
      socket: {
        remoteAddress: '127.0.0.1',
      },
    }

    mockReply = {
      code: vi.fn().mockReturnThis(),
      send: vi.fn().mockReturnThis(),
      header: vi.fn().mockReturnThis(),
    }

    // Clear module cache to reset store
    vi.resetModules()
  })

  it('should allow requests within rate limit', async () => {
    for (let i = 0; i < 50; i++) {
      await rateLimitMiddleware(
        mockRequest as FastifyRequest,
        mockReply as FastifyReply
      )
    }

    expect(mockReply.code).not.toHaveBeenCalledWith(429)
  })

  it('should reject requests exceeding rate limit', async () => {
    // Make 101 requests (exceeding limit of 100)
    for (let i = 0; i < 101; i++) {
      await rateLimitMiddleware(
        mockRequest as FastifyRequest,
        mockReply as FastifyReply
      )
    }

    expect(mockReply.code).toHaveBeenCalledWith(429)
    expect(mockReply.send).toHaveBeenCalledWith(
      expect.objectContaining({
        error: 'Too Many Requests',
      })
    )
  })

  it('should include rate limit headers', async () => {
    await rateLimitMiddleware(
      mockRequest as FastifyRequest,
      mockReply as FastifyReply
    )

    expect(mockReply.header).toHaveBeenCalledWith('X-RateLimit-Limit', expect.any(String))
    expect(mockReply.header).toHaveBeenCalledWith('X-RateLimit-Remaining', expect.any(String))
    expect(mockReply.header).toHaveBeenCalledWith('X-RateLimit-Reset', expect.any(String))
  })
})

