package redis

import (
	"context"
	"sync"
	"time"

	"bindbox-game/configs"
	"bindbox-game/internal/pkg/logger"

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

var (
	once   sync.Once
	client *redis.Client
)

// Init Initialize Redis client
func Init(ctx context.Context, logger logger.CustomLogger) error {
	var err error
	once.Do(func() {
		cfg := configs.Get().Redis
		client = redis.NewClient(&redis.Options{
			Addr:         cfg.Addr,
			Password:     cfg.Pass,
			DB:           cfg.DB,
			DialTimeout:  5 * time.Second,
			ReadTimeout:  3 * time.Second,
			WriteTimeout: 3 * time.Second,
			PoolSize:     20,
		})

		// Ping to verify connection
		pingCtx, cancel := context.WithTimeout(ctx, 3*time.Second)
		defer cancel()
		if err = client.Ping(pingCtx).Err(); err != nil {
			logger.Error("Failed to connect to Redis", zap.String("addr", cfg.Addr), zap.Error(err))
			return // err set above
		}
		logger.Info("Connected to Redis", zap.String("addr", cfg.Addr))
	})
	return err
}

// GetClient Returns the singleton Redis client
func GetClient() *redis.Client {
	if client == nil {
		// Should have been initialized. If not, panic or try init?
		// For safety in this strict environment, let's assume Init was called in main.
		// Panic might be safer to detect misuse early.
		panic("Redis client not initialized")
	}
	return client
}
