package redis

import (
	"context"
	"errors"
	"io"
	"log/slog"
	"testing"
	"time"
)

func TestIsRedisLoadingError(t *testing.T) {
	tests := []struct {
		err  error
		want bool
	}{
		{err: nil, want: false},
		{err: errors.New("LOADING Redis is loading the dataset in memory"), want: true},
		{err: errors.New("BUSYLOADING Redis is busy"), want: true},
		{err: errors.New("connection refused"), want: false},
	}
	for _, tt := range tests {
		if got := isRedisLoadingError(tt.err); got != tt.want {
			t.Fatalf("isRedisLoadingError(%q) = %v, want %v", tt.err, got, tt.want)
		}
	}
}

func TestRetryWhileRedisLoadingRecovers(t *testing.T) {
	logger := slog.New(slog.NewTextHandler(io.Discard, nil))
	attempts := 0

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	err := retryWhileRedisLoading(ctx, logger, "test", func() error {
		attempts++
		if attempts < 3 {
			return errors.New("LOADING Redis is loading the dataset in memory")
		}
		return nil
	})
	if err != nil {
		t.Fatalf("retryWhileRedisLoading: %v", err)
	}
	if attempts != 3 {
		t.Fatalf("attempts: got %d, want 3", attempts)
	}
}

func TestRetryWhileRedisLoadingNonLoadingError(t *testing.T) {
	logger := slog.New(slog.NewTextHandler(io.Discard, nil))
	want := errors.New("connection refused")

	err := retryWhileRedisLoading(context.Background(), logger, "test", func() error {
		return want
	})
	if !errors.Is(err, want) {
		t.Fatalf("got %v, want %v", err, want)
	}
}
