import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest'
import { checkRateLimit, RATE_LIMITS } from '@/lib/rate-limit'

describe('rate-limit', () => {
  beforeEach(() => {
    vi.useFakeTimers()
  })
  afterEach(() => {
    vi.useRealTimers()
  })

  it('allows the first request', () => {
    const result = checkRateLimit('test-key-1', { limit: 5, windowSec: 60 })
    expect(result.allowed).toBe(true)
    expect(result.remaining).toBe(4)
  })

  it('allows up to the limit, then rejects', () => {
    const key = 'test-key-2'
    const config = { limit: 3, windowSec: 60 }

    expect(checkRateLimit(key, config).allowed).toBe(true)
    expect(checkRateLimit(key, config).allowed).toBe(true)
    expect(checkRateLimit(key, config).allowed).toBe(true)
    expect(checkRateLimit(key, config).allowed).toBe(false)
    expect(checkRateLimit(key, config).allowed).toBe(false)
  })

  it('decrements the remaining counter on each call', () => {
    const key = 'test-key-3'
    const config = { limit: 3, windowSec: 60 }

    expect(checkRateLimit(key, config).remaining).toBe(2)
    expect(checkRateLimit(key, config).remaining).toBe(1)
    expect(checkRateLimit(key, config).remaining).toBe(0)
  })

  it('keys are isolated from each other', () => {
    const config = { limit: 1, windowSec: 60 }
    expect(checkRateLimit('key-a', config).allowed).toBe(true)
    expect(checkRateLimit('key-a', config).allowed).toBe(false)
    // Different key still has its quota
    expect(checkRateLimit('key-b', config).allowed).toBe(true)
  })

  it('resets after the window expires', () => {
    const key = 'test-key-reset'
    const config = { limit: 2, windowSec: 1 }

    expect(checkRateLimit(key, config).allowed).toBe(true)
    expect(checkRateLimit(key, config).allowed).toBe(true)
    expect(checkRateLimit(key, config).allowed).toBe(false)

    // Advance past the window
    vi.advanceTimersByTime(1100)

    expect(checkRateLimit(key, config).allowed).toBe(true)
  })

  it('exposes a sensible resetAt timestamp', () => {
    const before = Date.now()
    const r = checkRateLimit('reset-at-test', { limit: 5, windowSec: 60 })
    expect(r.resetAt).toBeGreaterThanOrEqual(before + 60_000 - 10)
    expect(r.resetAt).toBeLessThanOrEqual(before + 60_000 + 10)
  })

  describe('preset configs', () => {
    it('magicLink: 3 per hour', () => {
      expect(RATE_LIMITS.magicLink.limit).toBe(3)
      expect(RATE_LIMITS.magicLink.windowSec).toBe(3600)
    })

    it('authVerify: 10 per 15 minutes', () => {
      expect(RATE_LIMITS.authVerify.limit).toBe(10)
      expect(RATE_LIMITS.authVerify.windowSec).toBe(900)
    })

    it('chat: 20 per minute', () => {
      expect(RATE_LIMITS.chat.limit).toBe(20)
      expect(RATE_LIMITS.chat.windowSec).toBe(60)
    })
  })
})
