package db

import (
	"context"
	"server/conf"
	"server/pkg/github.com/name5566/leaf/log"
	"time"

	"github.com/redis/go-redis/v9"
)

var ctx = context.Background()

var Rdb *redis.Client

func InitRedis() {
	rdb := redis.NewClient(&redis.Options{
		Addr:     conf.Server.RedisAddr + ":" + conf.Server.RedisPort,
		Password: conf.Server.RedisPwd, // no password set
		DB:       conf.Server.RedisDb,
	})

	_, err := rdb.Ping(ctx).Result()
	if err != nil {
		log.Debug("连接redis出错，错误信息：%v", err)
		return
	}
	log.Debug("成功连接redis")
	Rdb = rdb
}

func RedisSetKey(key string, value string, expiration time.Duration) {
	err := Rdb.Set(ctx, key, value, expiration).Err()
	if err != nil {
		log.Debug("redis set failed, err:%v\n", err)
	}
}

// 获取锁
func RedisLock(key string, value string, expiration time.Duration) bool {
	ok, err := Rdb.SetNX(ctx, key, value, expiration).Result()
	if err != nil {
		log.Debug("redis lock failed, err:%v\n", err)
		return false
	}
	return ok
}

// 释放锁
func RedisUnlock(key string, value string) bool {
	script := `
    if redis.call("GET", KEYS[1]) == ARGV[1] then
        return redis.call("DEL", KEYS[1])
    else
        return 0
    end
    `
	result, err := Rdb.Eval(ctx, script, []string{key}, value).Result()
	if err != nil {
		log.Debug("redis unlock failed, err:%v\n", err)
		return false
	}
	return result.(int64) == 1
}

func RedisGetKey(key string) (string, error) {
	val, err := Rdb.Get(ctx, key).Result()
	if err != nil {
		return "", err
	}
	return val, nil
}

func RedisDelKey(key string) {
	err := Rdb.Del(ctx, key).Err()
	if err != nil {
		log.Debug("redis del failed, err:%v\n", err)
	}
}

func RedisZAdd(key string, member string, score float64) {
	err := Rdb.ZAdd(ctx, key, redis.Z{Score: score, Member: member}).Err()
	if err != nil {
		log.Debug("redis zadd failed, err:%v\n", err)
	}
}

func RedisZRangeWithScores(key string, start, stop int64) ([]redis.Z, error) {
	val, err := Rdb.ZRangeWithScores(ctx, key, start, stop).Result()
	if err != nil {
		return nil, err
	}
	return val, nil
}

func RedisZRevRangeWithScores(key string, start, stop int64) ([]redis.Z, error) {
	val, err := Rdb.ZRevRangeWithScores(ctx, key, start, stop).Result()
	if err != nil {
		return nil, err
	}
	return val, nil
}

func RedisZRankWithScores(key, member string) (int64, float64, error) {
	val, err := Rdb.ZRank(ctx, key, member).Result()
	if err != nil {
		return 0, 0, err
	}
	score, err := Rdb.ZScore(ctx, key, member).Result()
	if err != nil {
		return 0, 0, err
	}
	return val, score, nil
}

func RedisDel(key string) {
	err := Rdb.Del(ctx, key).Err()
	if err != nil {
		log.Debug("redis del failed, err:%v\n", err)
	}
}
