import { beforeEach, describe, expect, it, vi } from 'vitest'

const createdLimiters: any[] = []

vi.mock('express-rate-limit', () => ({
  default: vi.fn((config: any) => {
    createdLimiters.push(config)
    return config
  }),
  ipKeyGenerator: vi.fn((ip: string) => `ip:${ip}`),
}))

vi.mock('../security/tokens', () => ({
  verifyAnyActorToken: vi.fn((token: string) => {
    if (token === 'employee-token') return { type: 'employee', sub: 'employee_1' }
    if (token === 'renter-token') return { type: 'renter', sub: 'renter_1' }
    throw new Error('Invalid actor token')
  }),
}))

import rateLimit, { ipKeyGenerator } from 'express-rate-limit'

describe('rateLimiter middleware configuration', () => {
  beforeEach(() => {
    createdLimiters.length = 0
    vi.resetModules()
  })

  it('configures auth limiter to count failed attempts only', async () => {
    const { authLimiter } = await import('./rateLimiter')

    expect(authLimiter.max).toBe(20)
    expect(authLimiter.windowMs).toBe(15 * 60 * 1000)
    expect(authLimiter.skipSuccessfulRequests).toBe(true)
    expect(authLimiter.message).toMatchObject({ error: 'too_many_requests', statusCode: 429 })
    expect(rateLimit).toHaveBeenCalled()
  })

  it('keys general API limits by verified actor identity before falling back to request context', async () => {
    const { apiLimiter } = await import('./rateLimiter')

    expect(apiLimiter.keyGenerator({
      ip: '203.0.113.10',
      headers: { cookie: 'theme=dark; employee_session=employee-token' },
      companyId: 'company_1',
    } as any)).toBe('ip:203.0.113.10:employee:employee_1')
    expect(apiLimiter.keyGenerator({
      ip: '203.0.113.10',
      headers: { authorization: 'Bearer renter-token' },
      renterId: 'legacy_renter_context',
    } as any)).toBe('ip:203.0.113.10:renter:renter_1')
    expect(apiLimiter.keyGenerator({
      ip: '203.0.113.10',
      headers: { authorization: 'Bearer invalid-token' },
      companyId: 'company_1',
    } as any)).toBe('ip:203.0.113.10:company_1')
    expect(apiLimiter.keyGenerator({ ip: '203.0.113.10', headers: {}, renterId: 'renter_1' } as any)).toBe('ip:203.0.113.10:renter_1')
    expect(ipKeyGenerator).toHaveBeenCalledWith('203.0.113.10')
  })

  it('uses tighter public and admin limits with explicit 429 payloads', async () => {
    const { publicLimiter, adminLimiter } = await import('./rateLimiter')

    expect(publicLimiter.max).toBe(60)
    expect(publicLimiter.message.message).toBe('Rate limit exceeded')
    expect(adminLimiter.max).toBe(100)
    expect(adminLimiter.message.message).toBe('Too many admin requests')
  })
})
