package validator

import (
	"context"
	"testing"

	"github.com/redis/go-redis/v9"
	"github.com/stretchr/testify/mock"
	"go.uber.org/zap"

	"github.com/break/junhong_cmp_fiber/pkg/constants"
)

// BenchmarkTokenValidator_Validate 测试令牌验证性能
func BenchmarkTokenValidator_Validate(b *testing.B) {
	logger := zap.NewNop()

	b.Run("ValidToken", func(b *testing.B) {
		mockRedis := new(MockRedisClient)
		validator := NewTokenValidator(mockRedis, logger)

		// Mock Ping 成功
		pingCmd := redis.NewStatusCmd(context.Background())
		pingCmd.SetVal("PONG")
		mockRedis.On("Ping", mock.Anything).Return(pingCmd)

		// Mock Get 返回用户 ID
		getCmd := redis.NewStringCmd(context.Background())
		getCmd.SetVal("user_123")
		mockRedis.On("Get", mock.Anything, constants.RedisAuthTokenKey("test-token")).Return(getCmd)

		b.ResetTimer()
		for i := 0; i < b.N; i++ {
			_, _ = validator.Validate("test-token")
		}
	})

	b.Run("InvalidToken", func(b *testing.B) {
		mockRedis := new(MockRedisClient)
		validator := NewTokenValidator(mockRedis, logger)

		// Mock Ping 成功
		pingCmd := redis.NewStatusCmd(context.Background())
		pingCmd.SetVal("PONG")
		mockRedis.On("Ping", mock.Anything).Return(pingCmd)

		// Mock Get 返回 redis.Nil（令牌不存在）
		getCmd := redis.NewStringCmd(context.Background())
		getCmd.SetErr(redis.Nil)
		mockRedis.On("Get", mock.Anything, constants.RedisAuthTokenKey("invalid-token")).Return(getCmd)

		b.ResetTimer()
		for i := 0; i < b.N; i++ {
			_, _ = validator.Validate("invalid-token")
		}
	})

	b.Run("RedisUnavailable", func(b *testing.B) {
		mockRedis := new(MockRedisClient)
		validator := NewTokenValidator(mockRedis, logger)

		// Mock Ping 失败
		pingCmd := redis.NewStatusCmd(context.Background())
		pingCmd.SetErr(context.DeadlineExceeded)
		mockRedis.On("Ping", mock.Anything).Return(pingCmd)

		b.ResetTimer()
		for i := 0; i < b.N; i++ {
			_, _ = validator.Validate("test-token")
		}
	})
}

// BenchmarkTokenValidator_IsAvailable 测试可用性检查性能
func BenchmarkTokenValidator_IsAvailable(b *testing.B) {
	logger := zap.NewNop()
	mockRedis := new(MockRedisClient)
	validator := NewTokenValidator(mockRedis, logger)

	// Mock Ping 成功
	pingCmd := redis.NewStatusCmd(context.Background())
	pingCmd.SetVal("PONG")
	mockRedis.On("Ping", mock.Anything).Return(pingCmd)

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_ = validator.IsAvailable()
	}
}
