package cache_test

import (
	"context"
	"testing"
	"time"

	"github.com/alicebob/miniredis/v2"

	"github.com/user-management-system/internal/cache"
)

func TestRedisCache_EnabledRoundTrip(t *testing.T) {
	redisServer := miniredis.RunT(t)

	l2 := cache.NewRedisCacheWithConfig(cache.RedisCacheConfig{
		Enabled: true,
		Addr:    redisServer.Addr(),
	})
	t.Cleanup(func() {
		_ = l2.Close()
	})

	ctx := context.Background()
	if err := l2.Set(ctx, "login_attempt:user:7", 3, time.Minute); err != nil {
		t.Fatalf("set redis value failed: %v", err)
	}

	value, err := l2.Get(ctx, "login_attempt:user:7")
	if err != nil {
		t.Fatalf("get redis value failed: %v", err)
	}

	count, ok := value.(int64)
	if !ok || count != 3 {
		t.Fatalf("expected int64(3), got (%T) %v", value, value)
	}

	exists, err := l2.Exists(ctx, "login_attempt:user:7")
	if err != nil {
		t.Fatalf("exists failed: %v", err)
	}
	if !exists {
		t.Fatal("expected redis key to exist")
	}

	if err := l2.Delete(ctx, "login_attempt:user:7"); err != nil {
		t.Fatalf("delete failed: %v", err)
	}
	exists, err = l2.Exists(ctx, "login_attempt:user:7")
	if err != nil {
		t.Fatalf("exists after delete failed: %v", err)
	}
	if exists {
		t.Fatal("expected redis key to be deleted")
	}
}

func TestCacheManager_ReadsThroughRedisL2(t *testing.T) {
	redisServer := miniredis.RunT(t)

	l1 := cache.NewL1Cache()
	l2 := cache.NewRedisCacheWithConfig(cache.RedisCacheConfig{
		Enabled: true,
		Addr:    redisServer.Addr(),
	})
	t.Cleanup(func() {
		_ = l2.Close()
	})

	ctx := context.Background()
	if err := l2.Set(ctx, "email_daily:user@example.com:2026-03-18", 4, time.Minute); err != nil {
		t.Fatalf("seed redis value failed: %v", err)
	}

	manager := cache.NewCacheManager(l1, l2)
	value, ok := manager.Get(ctx, "email_daily:user@example.com:2026-03-18")
	if !ok {
		t.Fatal("expected cache manager to read from redis l2")
	}

	count, ok := value.(int64)
	if !ok || count != 4 {
		t.Fatalf("expected int64(4), got (%T) %v", value, value)
	}

	if err := l2.Delete(ctx, "email_daily:user@example.com:2026-03-18"); err != nil {
		t.Fatalf("delete redis seed failed: %v", err)
	}

	value, ok = manager.Get(ctx, "email_daily:user@example.com:2026-03-18")
	if !ok {
		t.Fatal("expected cache manager to rehydrate l1 after redis read")
	}
	if count, ok := value.(int64); !ok || count != 4 {
		t.Fatalf("expected l1 to retain int64(4), got (%T) %v", value, value)
	}
}
