import { describe, it, expect, beforeEach, vi } from 'vitest'
import { createMockEvent } from '../helpers/createMockEvent.js'

describe('rate-limit middleware', () => {
  // Fresh import per describe block to get fresh limiter instances
  let rateLimitMiddleware

  beforeEach(async () => {
    vi.resetModules()
    const mod = await import('../../../server/middleware/03.rate-limit.js')
    rateLimitMiddleware = mod.default
  })

  describe('non-API paths', () => {
    it('skips rate limiting for non-/api/ paths', async () => {
      const event = createMockEvent({ path: '/about', remoteAddress: '10.0.0.1' })
      await expect(rateLimitMiddleware(event)).resolves.toBeUndefined()
    })
  })

  describe('auth endpoint limiting (5 per 5 min)', () => {
    it('allows 5 requests then blocks the 6th', async () => {
      const ip = '10.0.1.1'

      // First 5 should succeed
      for (let i = 0; i < 5; i++) {
        const event = createMockEvent({
          method: 'POST',
          path: '/api/auth/login',
          remoteAddress: ip
        })
        await expect(rateLimitMiddleware(event)).resolves.toBeUndefined()
      }

      // 6th should be rate limited
      const event = createMockEvent({
        method: 'POST',
        path: '/api/auth/login',
        remoteAddress: ip
      })
      await expect(rateLimitMiddleware(event)).rejects.toMatchObject({
        statusCode: 429
      })

      // Check Retry-After header was set
      expect(event._testSetHeaders['retry-after']).toBeDefined()
    })
  })

  describe('payment endpoint limiting (10 per min)', () => {
    it('allows 10 requests then blocks the 11th', async () => {
      const ip = '10.0.2.1'

      for (let i = 0; i < 10; i++) {
        const event = createMockEvent({
          method: 'POST',
          path: '/api/helcim/initialize-payment',
          remoteAddress: ip
        })
        await expect(rateLimitMiddleware(event)).resolves.toBeUndefined()
      }

      const event = createMockEvent({
        method: 'POST',
        path: '/api/helcim/initialize-payment',
        remoteAddress: ip
      })
      await expect(rateLimitMiddleware(event)).rejects.toMatchObject({
        statusCode: 429
      })
    })
  })

  describe('IP isolation', () => {
    it('different IPs have separate rate limit counters', async () => {
      // Exhaust limit for IP A
      for (let i = 0; i < 5; i++) {
        const event = createMockEvent({
          method: 'POST',
          path: '/api/auth/login',
          remoteAddress: '10.0.3.1'
        })
        await rateLimitMiddleware(event)
      }

      // IP B should still be able to make requests
      const event = createMockEvent({
        method: 'POST',
        path: '/api/auth/login',
        remoteAddress: '10.0.3.2'
      })
      await expect(rateLimitMiddleware(event)).resolves.toBeUndefined()
    })
  })
})
