package redis

import (
	"context"
	"log/slog"
	"strings"
	"time"
)

func isRedisLoadingError(err error) bool {
	if err == nil {
		return false
	}
	msg := strings.ToLower(err.Error())
	return strings.Contains(msg, "loading redis") ||
		strings.Contains(msg, "loading the dataset") ||
		strings.Contains(msg, "busyloading")
}

func retryWhileRedisLoading(ctx context.Context, logger *slog.Logger, operation string, fn func() error) error {
	if logger == nil {
		logger = slog.Default()
	}

	backoff := 500 * time.Millisecond
	maxBackoff := 30 * time.Second

	for {
		err := fn()
		if err == nil {
			return nil
		}
		if !isRedisLoadingError(err) {
			return err
		}
		if ctx.Err() != nil {
			return ctx.Err()
		}

		logger.Warn("redis loading, retrying stream setup",
			"operation", operation,
			"backoff_ms", backoff.Milliseconds(),
			"error", err,
		)

		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-time.After(backoff):
		}

		backoff *= 2
		if backoff > maxBackoff {
			backoff = maxBackoff
		}
	}
}
