package distributedmutex

import (
	"context"
	"testing"
	"time"

	"github.com/redis/go-redis/v9"
	"go.uber.org/zap"
)

// mockRedisClient implements minimal required methods for testing
type mockRedisClient struct {
	redis.UniversalClient
}

func (m *mockRedisClient) Get(ctx context.Context, key string) *redis.StringCmd {
	return redis.NewStringCmd(ctx)
}

func (m *mockRedisClient) Set(ctx context.Context, key string, value any, expiration time.Duration) *redis.StatusCmd {
	return redis.NewStatusCmd(ctx)
}

func (m *mockRedisClient) Eval(ctx context.Context, script string, keys []string, args ...any) *redis.Cmd {
	return redis.NewCmd(ctx)
}

func (m *mockRedisClient) EvalSha(ctx context.Context, sha string, keys []string, args ...any) *redis.Cmd {
	return redis.NewCmd(ctx)
}

func (m *mockRedisClient) ScriptExists(ctx context.Context, scripts ...string) *redis.BoolSliceCmd {
	return redis.NewBoolSliceCmd(ctx)
}

func (m *mockRedisClient) ScriptLoad(ctx context.Context, script string) *redis.StringCmd {
	return redis.NewStringCmd(ctx)
}

func TestNewAdapter(t *testing.T) {
	logger, _ := zap.NewDevelopment()
	adapter := NewAdapter(logger, &mockRedisClient{})
	if adapter == nil {
		t.Fatal("expected non-nil adapter")
	}
}

func TestAcquireAndRelease(t *testing.T) {
	ctx := context.Background()
	logger, _ := zap.NewDevelopment()
	adapter := NewAdapter(logger, &mockRedisClient{})

	// Test basic acquire/release
	adapter.Acquire(ctx, "test-key")
	adapter.Release(ctx, "test-key")

	// Test formatted acquire/release
	adapter.Acquiref(ctx, "test-key-%d", 1)
	adapter.Releasef(ctx, "test-key-%d", 1)
}

func TestReleaseNonExistentLock(t *testing.T) {
	ctx := context.Background()
	logger, _ := zap.NewDevelopment()
	adapter := NewAdapter(logger, &mockRedisClient{})

	// This should not panic, just log a warning
	adapter.Release(ctx, "non-existent-key")
}
