package cache

import (
	"context"
	"eta/eta_mini_ht_api/common/component/config"
	logger "eta/eta_mini_ht_api/common/component/log"
	"eta/eta_mini_ht_api/common/contants"
	"github.com/go-redis/redis/v8"
	"log"
	"strings"
	"sync"
	"time"
)

var (
	redisCache *RedisCache
	redisOnce  sync.Once
)

func init() {
	if GetInstance() == nil {
		panic("初始化redis失败")
	}
	logger.Info("redis初始化成功")
}
func GetInstance() *RedisCache {
	redisOnce.Do(func() {
		// 检查是否成功获取到RedisConfig实例,没有配置则不进行redis初始化
		if redisConf, ok := config.GetConfig(contants.REDIS).(*config.RedisConfig); ok {
			if redisConf.GetHost() != "" {
				logger.Info("初始化redis")
				// 这里可以添加初始化Redis的逻辑
				redisCache = newRedis(redisConf)
				_, err := redisCache.Do("Ping")
				if err != nil {
					logger.Warn("redis 链接失败:%v", err)
				}
			} else {
				logger.Info("Redis configuration is incomplete: Host is missing")
				return
			}
		}
	})
	return redisCache
}
func newRedis(config *config.RedisConfig) *RedisCache {
	if &config == nil || config.GetHost() == "" {
		log.Fatalf("redis 连接失败")
	}
	redisTemplate := redis.NewUniversalClient(&redis.UniversalOptions{
		Addrs:        strings.Split(config.GetHost(), ","),
		DB:           config.GetDatabase(),
		Password:     config.GetPassword(),
		IdleTimeout:  time.Second * time.Duration(config.GetIdleTimeout()),
		MinIdleConns: config.GetMaxIdle(),
	})
	return &RedisCache{redisTemplate: redisTemplate}
}

// RedisCache
// @Description: redis缓存
type RedisCache struct {
	redisTemplate redis.UniversalClient
}

func (r *RedisCache) GetHSet(key string) map[string]string {
	return r.GetHSetWithContext(context.Background(), key)
}
func (r *RedisCache) GetHSetWithContext(ctx context.Context, key string) map[string]string {
	value, _ := r.redisTemplate.HGetAll(ctx, key).Result()
	return value
}

func (r *RedisCache) SetHSet(key string, timeout time.Duration, val ...interface{}) error {
	return r.SetHSetWithContext(context.Background(), key, timeout, val...)
}
func (r *RedisCache) SetHSetWithContext(ctx context.Context, key string, timeout time.Duration, val ...interface{}) error {
	err := r.redisTemplate.HSet(ctx, key, val...).Err()
	if err != nil {
		return err
	}
	return r.redisTemplate.Expire(ctx, key, timeout).Err()
}

// GetString  获取一个值
func (r *RedisCache) GetString(key string) string {
	return r.GetStringWithContext(context.Background(), key)

}

// GetStringWithContext  获取一个值
func (r *RedisCache) GetStringWithContext(ctx context.Context, key string) (value string) {
	value, _ = r.redisTemplate.Get(ctx, key).Result()
	return
}

// SetString 设置一个值
func (r *RedisCache) SetString(key string, val string, expired int) error {
	return r.SetStringWithContext(context.Background(), key, val, expired)
}

// SetStringWithContext  设置一个值
func (r *RedisCache) SetStringWithContext(ctx context.Context, key string, val string, expired int) error {
	return r.redisTemplate.SetEX(ctx, key, val, time.Duration(expired)*time.Second).Err()
}

// IsExist 判断key是否存在
func (r *RedisCache) IsExist(key string) bool {
	return r.IsExistWithContext(context.Background(), key)
}

// IsExistWithContext 判断key是否存在
func (r *RedisCache) IsExistWithContext(ctx context.Context, key string) bool {
	result, _ := r.redisTemplate.Exists(ctx, key).Result()
	return result > 0
}

// Delete 删除
func (r *RedisCache) Delete(key string) error {
	return r.DeleteWithContext(context.Background(), key)
}

// DeleteWithContext  删除
func (r *RedisCache) DeleteWithContext(ctx context.Context, key string) error {
	return r.redisTemplate.Del(ctx, key).Err()
}

// Do	执行指令
func (r *RedisCache) Do(commandName string, args ...interface{}) (reply interface{}, err error) {
	return r.DoWithContext(context.Background(), commandName, args...)
}

// DoWithContext 执行指令
func (r *RedisCache) DoWithContext(ctx context.Context, commandName string, args ...interface{}) (reply interface{}, err error) {
	newArgs := []interface{}{commandName}
	newArgs = append(newArgs, args...)
	return r.redisTemplate.Do(ctx, newArgs...).Result()
}
