package infra

import (
	"testing"
	"time"
)

func TestRateLimiterCleanup(t *testing.T) {
	t.Run("purga entries con lastSeen mas antiguo que maxAge", func(t *testing.T) {
		rl := RateLimiterNew(10, 20)
		// Inyectar manualmente una entry vieja
		rl.mu.Lock()
		rl.clients["old"] = &rateLimiterClient{tokens: 5, lastSeen: time.Now().Add(-time.Hour)}
		rl.clients["new"] = &rateLimiterClient{tokens: 5, lastSeen: time.Now()}
		rl.mu.Unlock()

		stop := RateLimiterCleanup(rl, 10*time.Minute, 30*time.Millisecond)
		defer stop()

		// Esperar al menos un tick
		time.Sleep(100 * time.Millisecond)

		rl.mu.Lock()
		_, oldExists := rl.clients["old"]
		_, newExists := rl.clients["new"]
		rl.mu.Unlock()

		if oldExists {
			t.Error("entry 'old' no fue purgada")
		}
		if !newExists {
			t.Error("entry 'new' fue purgada incorrectamente")
		}
	})

	t.Run("no purga entries recientes", func(t *testing.T) {
		rl := RateLimiterNew(10, 20)
		RateLimiterCheck(rl, "fresh")

		stop := RateLimiterCleanup(rl, 10*time.Minute, 30*time.Millisecond)
		defer stop()

		time.Sleep(100 * time.Millisecond)

		rl.mu.Lock()
		_, exists := rl.clients["fresh"]
		rl.mu.Unlock()
		if !exists {
			t.Error("entry reciente fue purgada incorrectamente")
		}
	})

	t.Run("stop detiene la goroutine sin panic", func(t *testing.T) {
		rl := RateLimiterNew(10, 20)
		stop := RateLimiterCleanup(rl, time.Second, 10*time.Millisecond)
		stop()
		// Si esto no panica, pasa
		time.Sleep(50 * time.Millisecond)
	})

	t.Run("stop es idempotente", func(t *testing.T) {
		rl := RateLimiterNew(10, 20)
		stop := RateLimiterCleanup(rl, time.Second, 10*time.Millisecond)
		stop()
		stop() // segunda llamada no debe panic
		stop() // tercera tampoco
	})
}
