package database

import (
	configs "ares/config"
	"context"
	"github.com/redis/go-redis/v9"
	"time"
)

var RedisClient *redis.Client
var RedisOptions *redis.Options
var ctx = context.Background()

func ConnectRedis() {
	redisURL := configs.AppConfig.RedisUrl
	if redisURL == "" {
		if configs.Logger != nil {
			configs.Logger.Warn("Warning: REDIS_URL is not set, continuing without Redis cache")
		}
		return
	}

	opt, err := redis.ParseURL(redisURL)
	if err != nil {
		if configs.Logger != nil {
			configs.Logger.Sugar().Warnf("Warning: Failed to parse Redis URL: %v, continuing without Redis cache", err)
		}
		RedisOptions = nil
		return
	}

	RedisOptions = opt
	RedisClient = redis.NewClient(opt)

	// Test connection
	_, err = RedisClient.Ping(ctx).Result()
	if err != nil {
		if configs.Logger != nil {
			configs.Logger.Sugar().Warnf("Warning: Failed to connect to Redis: %v, continuing without Redis cache", err)
		}
		RedisClient = nil
		RedisOptions = nil
		return
	}

	if configs.Logger != nil {
		configs.Logger.Info("Connected to Redis successfully")
	}
}

// Set stores a key-value pair in Redis with expiration
func Set(key string, value interface{}, expiration time.Duration) error {
	if RedisClient == nil {
		return nil // Gracefully handle when Redis is not available
	}
	return RedisClient.Set(ctx, key, value, expiration).Err()
}

// Get retrieves a value from Redis
func Get(key string) (string, error) {
	if RedisClient == nil {
		return "", redis.Nil // Return Nil error when Redis is not available
	}
	return RedisClient.Get(ctx, key).Result()
}

// Delete removes a key from Redis
func Delete(key string) error {
	if RedisClient == nil {
		return nil
	}
	return RedisClient.Del(ctx, key).Err()
}

// Exists checks if a key exists in Redis
func Exists(key string) (bool, error) {
	if RedisClient == nil {
		return false, nil
	}
	count, err := RedisClient.Exists(ctx, key).Result()
	return count > 0, err
}

// SetWithJSON stores a JSON-serializable value in Redis
func SetEx(key string, value interface{}, seconds int) error {
	if RedisClient == nil {
		return nil
	}
	return RedisClient.Set(ctx, key, value, time.Duration(seconds)*time.Second).Err()
}

// Increment increments a counter in Redis
func Increment(key string) (int64, error) {
	if RedisClient == nil {
		return 0, nil
	}
	return RedisClient.Incr(ctx, key).Result()
}

// Expire sets expiration time for a key
func Expire(key string, expiration time.Duration) error {
	if RedisClient == nil {
		return nil
	}
	return RedisClient.Expire(ctx, key, expiration).Err()
}

// FlushAll clears all keys in the current database
func FlushAll() error {
	if RedisClient == nil {
		return nil
	}
	if configs.Logger != nil {
		configs.Logger.Info("🧹 Clearing Redis Cache...")
	}
	return RedisClient.FlushDB(ctx).Err()
}
