using MessagePack;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Threading.Tasks;
using static CrazyStudio.Core.Common.Redis.RedisHelper;
using System.Collections.Concurrent;
using CrazyStudio.Core.Common.Redis.Dto;
using CCrazyStudio.Core.Common.Protocols;
using System.Threading.Channels;
using CrazyStudio.Core.Common.Status.Entities;
using System.Security.Cryptography;
using CrazyStudio.Core.Common.Tools.Extensions;

namespace CrazyStudio.Core.Common.Redis
{
    public class RedisHelper
    {
        private static IConnectionMultiplexer? _connMultiplexer;

        private IDatabase? _db;

        public enum SerializeType
        {
            Binary,   //二进制
            Json,     //Json
        }

        public event Action<RedisChannel, RedisValue>? GetSubscribeEvent;

        private RedisChannel _myServerChannel;

        public const string BroadcastChannelName = "BROADCAST";
        private RedisChannel _broadcastChannel = new RedisChannel(BroadcastChannelName, RedisChannel.PatternMode.Literal);

        private ConcurrentDictionary<string, RedisChannelEvent> _serverChannels = new ConcurrentDictionary<string, RedisChannelEvent>();

        private ISubscriber subscriber;

        private IServer _server;

        private string _myServerClusterTag = string.Empty;
        public RedisHelper(IConnectionMultiplexer connectionMultiplexer, string? dbIndex, string myServerClusterTag)
        {
            _connMultiplexer = connectionMultiplexer;

            //这里选配置文件中的数据库
            var dbIdx = dbIndex ?? "0";
            SelectDB(Convert.ToInt32(dbIdx));
            subscriber = connectionMultiplexer.GetSubscriber();

            _myServerChannel = new RedisChannel(myServerClusterTag, RedisChannel.PatternMode.Literal);
            _serverChannels[myServerClusterTag] = new RedisChannelEvent
            {
                RedisChannel = _myServerChannel,
                GetSubscribeEvent = GetSubscribeEvent
            };
            _serverChannels[BroadcastChannelName] = new RedisChannelEvent
            {
                RedisChannel = _broadcastChannel,
                GetSubscribeEvent = GetSubscribeEvent
            };

            this._myServerClusterTag = myServerClusterTag;
        }


        public async Task SubscribeSystemChannels()
        {
            await subscriber.SubscribeAsync(_myServerChannel, GetSubscribeEvent!);
            await subscriber.SubscribeAsync(_broadcastChannel, GetSubscribeEvent!);

            //if (!string.IsNullOrWhiteSpace(_myServerClusterTag))
            //{
            //    await BroadcastAsync(new ClusterMessage
            //    {
            //        MsgType = XNetEventKeys.CLUSTER_JOIN,
            //        MsgContent = Encoding.UTF8.GetBytes(_myServerClusterTag)
            //    });
            //}
        }

        public async Task DeleteRedisCacheForThisServer()
        {
            try
            {
                //lock
                var userPrefix = Global.ServerToken + ":usr:";
                //var roomPrefix = "room:";
                int pageSize = 50;

                // 使用 SCAN 命令获取所有键，并应用正则表达式过滤
                var regex = new Regex(userPrefix);
                int count = 0;
                int nextCursor = 0; // 初始游标为0
                var res = _server.KeysAsync(-1, default, pageSize, 0).ToBlockingEnumerable();
                do
                {
                    var keys = res.Where(k => k.ToString().Contains(userPrefix)).Take(pageSize).ToArray();
                    count = keys.Length;
                    nextCursor += count;
                    if (count > 0)
                    {
                        await _db!.KeyDeleteAsync(keys);
                        //这里用RoomInfo的集合查询，批量删除
                    }

                } while (nextCursor != 0 && count > 0); // 当游标为0时结束循环
                //release
            }
            catch (RedisTimeoutException ex)
            {
                Console.WriteLine($"Redis操作超时: {ex.Message}");
                // 可添加重试逻辑
            }
        }

        public async Task SubscribeAsync(string channelName, Action<RedisChannel, RedisValue>? getSubscribeEvent)
        {
            if (subscriber != null && !string.IsNullOrEmpty(channelName))
            {
                if (!_serverChannels.TryGetValue(channelName, out RedisChannelEvent? channelEvent))
                {
                    channelEvent = new RedisChannelEvent
                    {
                        RedisChannel = new RedisChannel(channelName, RedisChannel.PatternMode.Literal),
                        GetSubscribeEvent = getSubscribeEvent
                    };

                    _serverChannels[channelName] = channelEvent;
                    await subscriber.SubscribeAsync(channelEvent.RedisChannel, channelEvent.GetSubscribeEvent!);
                }
            }
        }

        public async Task UnsubscribeAsync(string channelName)
        {
            if (subscriber != null && !string.IsNullOrEmpty(channelName))
            {
                if (_serverChannels.TryRemove(channelName, out RedisChannelEvent? channelEvent))
                {
                    await subscriber.UnsubscribeAsync(channelEvent!.RedisChannel, channelEvent.GetSubscribeEvent!);
                }
            }
        }

        public async Task SubscribeUsersChannels()
        {
            if (subscriber != null)
            {
                foreach (var channel in _serverChannels)
                {
                    if (channel.Key != BroadcastChannelName && channel.Key != _myServerClusterTag)
                    {
                        await subscriber.SubscribeAsync(channel.Value.RedisChannel, channel.Value.GetSubscribeEvent!);
                    }
                }
            }
        }

        public async Task UnsubscribeAllAsync()
        {
            if (subscriber != null)
            {
                await subscriber.UnsubscribeAllAsync();
            }
        }

        //public RedisHelper()
        //{
        //}

        //private void SetGreenTipColor()
        //{

        //}
        //private void SetWhiteTipColor()
        //{

        //}


        public void SelectDB(int dbIndex)
        {
            _db = _connMultiplexer?.GetDatabase(dbIndex);
            _server = _connMultiplexer!.GetServer(_connMultiplexer.GetEndPoints()[0]);
        }


        private RedisChannelEvent GetChannelEvent(string clusterServer)
        {
            if (!_serverChannels.TryGetValue(clusterServer, out RedisChannelEvent? channelEvent))
            {
                channelEvent = new RedisChannelEvent
                {
                    RedisChannel = new RedisChannel(clusterServer, RedisChannel.PatternMode.Literal),
                    GetSubscribeEvent = GetSubscribeEvent
                };
                _serverChannels[clusterServer] = channelEvent;
            }
            return channelEvent;
        }

        /// <summary>
        /// 发布
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task PublishAsync(string clusterServer, RedisValue message)
        {
            if (subscriber != null)
            {
                var channelEvent = GetChannelEvent(clusterServer);
                await subscriber.PublishAsync(channelEvent.RedisChannel, message);
            }
        }

        /// <summary>
        /// 发布（使用序列化）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="channel"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task PublishAsync<T>(string clusterServer, T message)
        {
            if (subscriber != null)
            {
                var channelEvent = GetChannelEvent(clusterServer);
                await subscriber.PublishAsync(channelEvent.RedisChannel, Serialize(message!));
            }
        }


        /// <summary>
        /// 广播
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task BroadcastAsync(RedisValue message)
        {
            await PublishAsync(BroadcastChannelName, message);
        }

        /// <summary>
        /// 广播（使用序列化）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="channel"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public async Task BroadcastAsync<T>(T message)
        {
            await PublishAsync(BroadcastChannelName, message);
        }

        public void Dispose()
        {
            _serverChannels.Clear();
            if (subscriber != null)
            {
                subscriber.UnsubscribeAll();
            }
        }

        /// <summary>
        /// 获取连接状态
        /// </summary>
        public bool ConnectStatus
        {
            get
            {
                if (_connMultiplexer != null)
                {
                    return _connMultiplexer.IsConnected;
                }
                else
                {
                    return false;
                }
            }
        }

        /// <summary>
        /// 给键添加前缀
        /// </summary>
        /// <param name="prefixName">前缀名称</param>
        /// <param name="keyName">键名称</param>
        /// <returns>返回添加前缀后的键</returns>
        public string AddPrefixOfKey(string prefixName, string keyName)
        {
            string str = $"{prefixName}:{keyName}";
            return str;
        }

        #region string操作

        public bool SetString(string key, string value, TimeSpan? expiry = null)
        {
            if (ConnectStatus)
            {
                return _db!.StringSet(key, value, expiry);
            }
            return false;

        }

        public string? GetString(string key, TimeSpan? expiry = null)
        {
            if (ConnectStatus)
            {
                return _db!.StringGet(key);
            }
            return string.Empty;
        }

        /// <summary>
        /// 保存多个多个键值对字符串
        /// </summary>
        /// <param name="keyValuePairs">键值对容器</param>
        /// <returns>返回结果（true表示成功）</returns>
        public bool SetString(IEnumerable<KeyValuePair<string, string>> keyValuePairs)
        {
            if (ConnectStatus)
            {
                var pairs = keyValuePairs.Select(it => new KeyValuePair<RedisKey, RedisValue>(it.Key, it.Value));
                return _db!.StringSet(pairs.ToArray());
            }
            return false;
        }

        public bool SetObj<T>(string key, T value, TimeSpan? expiry = null, SerializeType serializeType = SerializeType.Binary)
        {
            if (ConnectStatus)
            {
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        var binaryValue = Serialize(value!);
                        return _db!.StringSet(key, binaryValue, expiry);

                    case SerializeType.Json:
                        var jsonValue = SerializeJson(value);
                        return _db!.StringSet(key, jsonValue, expiry);
                    default: return false;
                }
            }
            return false;
        }

        public T? GetObj<T>(string key, TimeSpan? expiry = null, SerializeType serializeType = SerializeType.Binary)
        {
            if (ConnectStatus)
            {
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        return Deserialize<T>(_db!.StringGet(key)!);
                    case SerializeType.Json:
                        return DeserializeJson<T>(_db!.StringGet(key)!);
                    default:
                        return default;
                }
            }
            return default;
        }

        public bool KeyDelete(string key)
        {
            if (ConnectStatus)
            {
                return _db!.KeyDelete(key);
            }
            return false;
        }
        public async Task<bool> KeyDeleteAsync(string key)
        {
            if (ConnectStatus)
            {
                return await _db!.KeyDeleteAsync(key).ConfigureAwait(false);
            }
            return false;
        }

        public bool KeyExists(string key)
        {
            if (ConnectStatus)
            {
                return _db!.KeyExists(key);
            }
            return false;
        }

        public async Task<bool> KeyExistsAsync(string key)
        {
            if (ConnectStatus)
            {
                return await _db!.KeyExistsAsync(key).ConfigureAwait(false);
            }
            return false;
        }

        /// <summary>
        /// 当前值+1，如果不存在key则新建一个key,值为1
        /// </summary>
        /// <param name="key"></param>
        public void IncrKey(string key)
        {
            if (ConnectStatus)
            {
                _db!.StringIncrement(key);
            }
        }

        /// <summary>
        /// 当前值+1，如果不存在key则新建一个key,值为1
        /// </summary>
        /// <param name="key"></param>
        public async Task IncrKeyAsync(string key)
        {
            if (ConnectStatus)
            {
                await _db!.StringIncrementAsync(key);
            }
        }
        /// <summary>
        /// 保存一个键值对字符串（异步方式）
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <param name="redisValue">值</param>
        /// <param name="expiry">时间间隔</param>
        /// <returns>返回结果（true表示成功）</returns>
        public async Task<bool> SetStringAsync(string redisKey, string redisValue, TimeSpan? expiry = null)
        {
            if (ConnectStatus)
            {
                return await _db!.StringSetAsync(redisKey, redisValue, expiry);
            }
            else
            {
                return false;
            }

        }

        /// <summary>
        /// 获取单个值
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <param name="redisValue">值</param>
        /// <param name="expiry">时间间隔</param>
        /// <returns>返回结果（true表示成功）</returns>
        public async Task<string?> GetStringAsync(string redisKey)
        {
            if (ConnectStatus)
            {
                return await _db!.StringGetAsync(redisKey);
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 保存一组字符串值
        /// </summary>
        /// <param name="keyValuePairs">键值对容器</param>
        /// <returns>返回结果（true表示成功）</returns>
        public async Task<bool> SetStringAsync(IEnumerable<KeyValuePair<string, string>> keyValuePairs)
        {
            if (ConnectStatus)
            {
                var pairs = keyValuePairs.Select(x => new KeyValuePair<RedisKey, RedisValue>(x.Key, x.Value));
                return await _db!.StringSetAsync(pairs.ToArray());
            }
            else
            {
                return false;
            }
        }



        /// <summary>
        /// 存储一个对象（该对象会被序列化保存）
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="expiry">间隔时间</param>
        /// <param name="serializeType">序列化类型（默认序列化为Json）</param> 
        /// <returns>返回结果（true表示成功）</returns>
        public async Task<bool> SetObjAsync<T>(string key, T value, TimeSpan? expiry = null,
            SerializeType serializeType = SerializeType.Binary)
        {
            if (ConnectStatus)
            {
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        var binaryValue = Serialize(value!);
                        return await _db!.StringSetAsync(key, binaryValue, expiry);

                    case SerializeType.Json:
                        var jsonValue = SerializeJson(value);
                        return await _db!.StringSetAsync(key, jsonValue, expiry);

                    default:
                        break;
                }
                return false;
            }
            else
            {
                return false;
            }
        }

        public async Task LockTakeAsync(string key, RedisValue token, SerializeType serializeType = SerializeType.Binary)
        {
            await _db!.LockTakeAsync(key, token, TimeSpan.MaxValue).ConfigureAwait(false);
        }

        public void LockTake(string key, RedisValue token, SerializeType serializeType = SerializeType.Binary)
        {
            _db!.LockTake(key, token, TimeSpan.MaxValue);
        }

        public async Task LockReleaseAsync(string key, RedisValue token, SerializeType serializeType = SerializeType.Binary)
        {
            await _db!.LockReleaseAsync(key, token).ConfigureAwait(false);
        }

        public void LockRelease(string key, RedisValue token, SerializeType serializeType = SerializeType.Binary)
        {
            _db!.LockRelease(key, token);
        }


        //public async Task LockRelease<T>(string key, T value, SerializeType serializeType = SerializeType.Binary)
        //{
        //    switch (serializeType)
        //    {
        //        case SerializeType.Binary:
        //            await _db!.LockReleaseAsync(key, Serialize(value!)).ConfigureAwait(false);
        //            break;
        //        case SerializeType.Json:
        //            await _db!.LockReleaseAsync(key, SerializeJson(value!)).ConfigureAwait(false);
        //            break;
        //        default:
        //            break;
        //    }
        //}

        /// <summary>
        /// 获取一个对象（会进行反序列化）
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="expiry">间隔时间</param>
        /// <param name="serializeType">序列化类型（默认序列化为Json）</param> 
        /// <returns>返回结果（true表示成功）</returns>
        public async Task<T?> GetObjAsync<T>(string key,
            SerializeType serializeType = SerializeType.Binary)
        {
            if (ConnectStatus)
            {
                var data = await _db!.StringGetAsync(key).ConfigureAwait(false);
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        return Deserialize<T>(data!);

                    case SerializeType.Json:
                        return DeserializeJson<T>(data!);

                    default:
                        break;
                }
                return default;
            }
            else
            {
                return default;
            }

        }


        #region Redis List

        /// <summary>
        /// 在列表尾部插入值。如果键不存在，先创建再插入值
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <param name="redisValue">值</param>
        /// <returns></returns>
        public long PushKeyInToListLast(string redisKey, string redisValue)
        {
            if (ConnectStatus)
            {
                return _db!.ListRightPush(redisKey, redisValue);
            }
            else
            {
                return -1;
            }
        }

        /// <summary>
        /// 在列表尾部插入值。如果键不存在，先创建再插入值
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <param name="redisValue">值</param>
        /// <returns></returns>
        public long PushKeyInToListLast(string redisKey, IEnumerable<string> redisValue)
        {
            if (ConnectStatus)
            {
                var val = redisValue.Select(x => (RedisValue)x);

                return _db!.ListRightPush(redisKey, val.ToArray());
            }
            else
            {
                return -1;
            }
        }

        /// <summary>
        /// 在列表头部插入值。如果键不存在，先创建再插入值
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <param name="redisValue">值</param>
        /// <returns></returns>
        public long PushKeyInToListFirst(string redisKey, string redisValue)
        {
            if (ConnectStatus)
            {
                return _db!.ListLeftPush(redisKey, redisValue);
            }
            else
            {
                return -1;
            }
        }


        /// <summary>
        /// 返回列表上该键的长度，如果不存在，返回 0
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <returns>返回结果（-1 表示失败）</returns>
        public long GetKeyLengthOfList(string redisKey)
        {
            if (ConnectStatus)
            {
                return _db!.ListLength(redisKey);
            }
            else
            {
                return -1;
            }
        }

        //public IEnumerable<string?>? ListRange(string redisKey, long start = 0L, long stop = -1L)
        //{
        //    if (ConnectStatus)
        //    {
        //        return ConvertStrings(_db!.ListRange(redisKey, start, stop));
        //    }
        //    return null;
        //}

        //public async Task<List<T>?> SortRange<T>(string redisKey, long start = 0L, long stop = -1L, SerializeType serializeType = SerializeType.Binary)
        //{
        //    List<T> result = new List<T>();
        //    if (ConnectStatus)
        //    {
        //        var redisList = await _db!.SortAsync(redisKey, by: "UserCount", sortType: SortType.Numeric, order: Order.Descending, skip: start, take: stop - start);
        //        //var redisList = await _db!.ListRangeAsync(redisKey, start, stop).ConfigureAwait(false);
        //        switch (serializeType)
        //        {
        //            case SerializeType.Binary:
        //                foreach (var item in redisList)
        //                {
        //                    var listValue = Deserialize<T>(item!)!;
        //                    result.Add(listValue);
        //                }
        //                break;
        //            case SerializeType.Json:
        //                foreach (var item in redisList)
        //                {
        //                    var listValue = DeserializeJson<T>(item!)!;
        //                    result.Add(listValue);
        //                }
        //                break;
        //            default:
        //                return default;
        //        }
        //    }
        //    return result;
        //}

        public async Task<long> ListRemove<T>(string redisKey, T value, CommandFlags flags = CommandFlags.None, SerializeType serializeType = SerializeType.Binary)
        {
            long result = 0;
            if (ConnectStatus)
            {
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        var binaryValue = Serialize(value!);
                        result = await _db!.ListRemoveAsync(redisKey, binaryValue, 0, flags).ConfigureAwait(false);
                        break;

                    case SerializeType.Json:
                        var jsonValue = SerializeJson(value);
                        result = await _db!.ListRemoveAsync(redisKey, jsonValue, 0, flags).ConfigureAwait(false);
                        break;
                    default:
                        break;
                }
            }
            return result;
        }

        public async Task ListSetByIndexAsync<T>(string redisKey, long index, T value, CommandFlags flags = CommandFlags.None, SerializeType serializeType = SerializeType.Binary)
        {
            if (ConnectStatus)
            {
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        var binaryValue = Serialize(value!);
                        await _db!.ListSetByIndexAsync(redisKey, index, binaryValue, flags).ConfigureAwait(false);
                        break;

                    case SerializeType.Json:
                        var jsonValue = SerializeJson(value);
                        await _db!.ListSetByIndexAsync(redisKey, index, jsonValue, flags).ConfigureAwait(false);
                        break;
                    default:
                        break;
                }
            }
        }

        public async Task<sbyte> SortedSetAddAsync<T>(string redisKey, T value, double score, CommandFlags flags = CommandFlags.None, SerializeType serializeType = SerializeType.Binary)
        {
            if (ConnectStatus)
            {
                bool isOK = false;
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        var binaryValue = Serialize(value!);
                        isOK = await _db!.SortedSetAddAsync(redisKey, binaryValue, score, flags).ConfigureAwait(false);

                        break;

                    case SerializeType.Json:
                        var jsonValue = SerializeJson(value);
                        isOK = await _db!.SortedSetAddAsync(redisKey, jsonValue, score, flags).ConfigureAwait(false);
                        break;
                    default:
                        break;
                }
                if (isOK)
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
            return -1;
        }

        public sbyte SortedSetAdd<T>(string redisKey, T value, double score, CommandFlags flags = CommandFlags.None, SerializeType serializeType = SerializeType.Binary)
        {
            if (ConnectStatus)
            {
                bool isOK = false;
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        var binaryValue = Serialize(value!);
                        isOK = _db!.SortedSetAdd(redisKey, binaryValue, score, flags);

                        break;

                    case SerializeType.Json:
                        var jsonValue = SerializeJson(value);
                        isOK = _db!.SortedSetAdd(redisKey, jsonValue, score, flags);
                        break;
                    default:
                        break;
                }
                if (isOK)
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
            return -1;
        }

        public async Task SortedSetRemoveAsync<T>(string redisKey, T value, CommandFlags flags = CommandFlags.None, SerializeType serializeType = SerializeType.Binary)
        {
            if (ConnectStatus)
            {
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        var binaryValue = Serialize(value!);
                        await _db!.SortedSetRemoveAsync(redisKey, binaryValue, flags).ConfigureAwait(false);
                        break;

                    case SerializeType.Json:
                        var jsonValue = SerializeJson(value);
                        await _db!.SortedSetRemoveAsync(redisKey, jsonValue, flags).ConfigureAwait(false);
                        break;
                    default:
                        break;
                }
            }
        }

        public void SortedSetRemove<T>(string redisKey, T value, CommandFlags flags = CommandFlags.None, SerializeType serializeType = SerializeType.Binary)
        {
            if (ConnectStatus)
            {
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        var binaryValue = Serialize(value!);
                        _db!.SortedSetRemoveAsync(redisKey, binaryValue, flags);
                        break;

                    case SerializeType.Json:
                        var jsonValue = SerializeJson(value);
                        _db!.SortedSetRemoveAsync(redisKey, jsonValue, flags);
                        break;
                    default:
                        break;
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="redisKey"></param>
        /// <param name="pageOffset"></param>
        /// <param name="pageSize"></param>
        /// <param name="pattern">模糊搜索 *XXX*</param>
        /// <param name="cursor"></param>
        /// <param name="flags"></param>
        /// <param name="serializeType"></param>
        /// <returns></returns>
        public List<T> SortedSetScan<T>(string redisKey, long pageOffset, int pageSize = 100, RedisValue pattern = default, CommandFlags flags = CommandFlags.None, SerializeType serializeType = SerializeType.Binary)
        {
            List<T> result = new List<T>();
            if (ConnectStatus)
            {
                var values = _db!.SortedSetScan(redisKey, pattern, pageSize, pageOffset, 0, flags);

                if (pageSize != -1)
                {
                    values = values.Take(pageSize);
                }
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        foreach (var item in values)
                        {
                            var listValue = Deserialize<T>(item.Element!)!;
                            result.Add(listValue);
                        }
                        break;

                    case SerializeType.Json:
                        foreach (var item in values)
                        {
                            var listValue = DeserializeJson<T>(item.Element!)!;
                            result.Add(listValue);
                        }
                        break;
                    default:
                        break;
                }
            }
            return result;
        }

        public async Task<T> SortedSetPopAsync<T>(string redisKey, Order order = Order.Ascending, CommandFlags flags = CommandFlags.None, SerializeType serializeType = SerializeType.Binary)
        {
            T? result = default;
            if (ConnectStatus)
            {
                var entry = await _db!.SortedSetPopAsync(redisKey, order, flags);
                var value = entry.GetValueOrDefault();
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        result = Deserialize<T>(value.Element!)!;
                        break;

                    case SerializeType.Json:
                        result = DeserializeJson<T>(value.Element!)!;
                        break;
                    default:
                        break;
                }
            }
            return result!;
        }


        public async Task<long> ListRightPushAsync<T>(string redisKey, T value, When when = When.Always, CommandFlags flags = CommandFlags.None, SerializeType serializeType = SerializeType.Binary)
        {
            long result = 0;
            if (ConnectStatus)
            {
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        var binaryValue = Serialize(value!);
                        result = await _db!.ListRightPushAsync(redisKey, binaryValue, when, flags).ConfigureAwait(false);
                        break;

                    case SerializeType.Json:
                        var jsonValue = SerializeJson(value);
                        result = await _db!.ListRightPushAsync(redisKey, jsonValue, when, flags).ConfigureAwait(false);
                        break;
                    default:
                        break;
                }
            }
            return result;
        }


        public async Task<long> ListLeftPushAsync<T>(string redisKey, T value, When when = When.Always, CommandFlags flags = CommandFlags.None, SerializeType serializeType = SerializeType.Binary)
        {
            long result = 0;
            if (ConnectStatus)
            {
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        var binaryValue = Serialize(value!);
                        result = await _db!.ListLeftPushAsync(redisKey, binaryValue, when, flags).ConfigureAwait(false);
                        break;

                    case SerializeType.Json:
                        var jsonValue = SerializeJson(value);
                        result = await _db!.ListLeftPushAsync(redisKey, jsonValue, when, flags).ConfigureAwait(false);
                        break;
                    default:
                        break;
                }
            }
            return result;
        }

        public async Task<long> ListLengthAsync(string redisKey)
        {
            long result = 0;
            if (ConnectStatus)
            {
                result = await _db!.ListLengthAsync(redisKey).ConfigureAwait(false);
            }
            return result;
        }

        public async Task<long> SortedSetLengthAsync(string redisKey)
        {
            long result = 0;
            if (ConnectStatus)
            {
                result = await _db!.SortedSetLengthAsync(redisKey).ConfigureAwait(false);
            }
            return result;
        }
        //public async Task<List<T>?> HashValuesAsync<T>(string redisKey, SerializeType serializeType = SerializeType.Binary)
        //{
        //    List<T> result = new List<T>();
        //    if (ConnectStatus)
        //    {
        //        var redisHashValues = await _db!.HashValuesAsync(redisKey).ConfigureAwait(false);
        //        switch (serializeType)
        //        {
        //            case SerializeType.Binary:
        //                foreach (var item in redisHashValues)
        //                {
        //                    var listValue = Deserialize<T>(item!)!;
        //                    result.Add(listValue);
        //                }
        //                break;
        //            case SerializeType.Json:
        //                foreach (var item in redisHashValues)
        //                {
        //                    var listValue = DeserializeJson<T>(item!)!;
        //                    result.Add(listValue);
        //                }
        //                break;
        //            default:
        //                return result;
        //        }
        //    }
        //    return result;
        //}

        public async Task<T?> HashValuesAsync<T>(string redisKey, SerializeType serializeType = SerializeType.Binary)
        {
            T? result = default;
            if (ConnectStatus)
            {
                var redisHashValues = await _db!.HashValuesAsync(redisKey).ConfigureAwait(false);
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        result = Deserialize<T>(redisHashValues[0]!)!;
                        break;
                    case SerializeType.Json:
                        result = DeserializeJson<T>(redisHashValues[0]!)!;
                        break;
                    default:
                        return result;
                }
            }
            return result;
        }

        #endregion


        #region Hasn操作


        /// <summary>
        /// 判断该字段是否存在hash中
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <param name="hashField">字段</param>
        /// <returns>返回结果（true：表示成功）</returns>
        public bool ExistsHash(string redisKey, string hashField)
        {
            if (ConnectStatus)
            {
                return _db!.HashExists(redisKey, hashField);
            }
            else
            {
                return false;
            }
        }


        /// <summary>
        /// 从 hash 中移除指定字段
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <param name="hashField">字段</param>
        /// <returns>返回结果（true：表示成功）</returns>
        public bool DeleteHash(string redisKey, string hashField)
        {
            if (ConnectStatus)
            {
                return _db!.HashDelete(redisKey, hashField);
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 从 hash 中移除指定字段
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <param name="hashFields">字段</param>
        /// <returns>返回结果（-1：表示失败）</returns>
        public long DeleteHash(string redisKey, IEnumerable<string> hashFields)
        {
            if (ConnectStatus)
            {
                var fields = hashFields.Select(x => (RedisValue)x);

                return _db!.HashDelete(redisKey, fields.ToArray());
            }
            else
            {
                return -1;
            }
        }

        /// <summary>
        /// 在 hash 设定值
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <param name="hashField">字段</param>
        /// <param name="value">值</param>
        /// <returns>返回结果（true：表示成功）</returns>
        public bool SetHash(string redisKey, string hashField, string value)
        {
            if (ConnectStatus)
            {
                return _db!.HashSet(redisKey, hashField, value);
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 在 hash 中设定值
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <param name="hashFields">字段容器</param>
        public void SetHash(string redisKey, IEnumerable<KeyValuePair<string, string>> hashFields)
        {
            if (ConnectStatus)
            {
                var entries = hashFields.Select(x => new HashEntry(x.Key, x.Value));

                _db!.HashSet(redisKey, entries.ToArray());
            }

        }

        /// <summary>
        /// 在 hash 中获取值
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <param name="hashField">字段</param>
        /// <returns>返回结果</returns>
        public string? GetHash(string redisKey, string hashField)
        {
            if (ConnectStatus)
            {
                return _db!.HashGet(redisKey, hashField);
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 在hash获取值
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <param name="hashFields">字段</param>
        /// <returns>返回结果</returns>
        public IEnumerable<string>? GetHash(string redisKey, IEnumerable<string> hashFields)
        {
            if (ConnectStatus)
            {
                var fields = hashFields.Select(x => (RedisValue)x);

                return ConvertStrings(_db!.HashGet(redisKey, fields.ToArray()));
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 从 hash 返回所有的字段值
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <returns>返回结果</returns>
        public IEnumerable<string>? HashKeys(string redisKey)
        {
            if (ConnectStatus)
            {
                return ConvertStrings(_db!.HashKeys(redisKey));
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 根据键获取hash中的所有值
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <returns>返回hash结果</returns>
        public IEnumerable<string>? HashValues(string redisKey)
        {
            if (ConnectStatus)
            {
                return ConvertStrings(_db!.HashValues(redisKey));
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 在 hash 设定值（序列化）
        /// </summary>
        /// <param name="redisKey">键</param>
        /// <param name="hashField">字段</param>
        /// <param name="redisValue">值</param>
        /// <param name="serializeType">序列化的类型（默认是MessagePack）</param>
        /// <returns>返回结果（true:表示成功）</returns>
        public bool SetObjHash<T>(string redisKey, string hashField, T redisValue,
            SerializeType serializeType = SerializeType.Binary)
        {
            if (ConnectStatus)
            {
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        var binaryValue = Serialize(redisValue!);
                        return _db!.HashSet(redisKey, hashField, binaryValue);

                    case SerializeType.Json:
                        var jsonValue = SerializeJson(redisValue);
                        return _db!.HashSet(redisKey, hashField, jsonValue);

                    default:
                        return false;

                }

            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 在 hash 中获取值（反序列化）
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <param name="serializeType">序列化的类型（默认是Json）</param>
        /// <returns></returns>
        public T GetObjHash<T>(string redisKey, string hashField,
            SerializeType serializeType = SerializeType.Binary)
        {
            if (ConnectStatus)
            {
                switch (serializeType)
                {
                    case SerializeType.Binary:
                        return Deserialize<T>(_db!.HashGet(redisKey, hashField)!);

                    case SerializeType.Json:
                        return DeserializeJson<T>(_db!.HashGet(redisKey, hashField)!);

                    default:
                        return default!;
                }

            }
            else
            {
                return default!;
            }
        }

        #endregion

        //#region 发布订阅

        //#region   同步方式
        ///// <summary>
        ///// 订阅
        ///// </summary>
        ///// <param name="channel"></param>
        ///// <param name="handle"></param>
        //public void Subscribe(RedisChannel channel, Action<RedisChannel, RedisValue> handle)
        //{
        //    var sub = _connMultiplexer.GetSubscriber();
        //    sub.Subscribe(channel, handle);
        //}

        ///// <summary>
        ///// 发布
        ///// </summary>
        ///// <param name="channel"></param>
        ///// <param name="message"></param>
        ///// <returns></returns>
        //public long Publish(RedisChannel channel, RedisValue message)
        //{
        //    var sub = _connMultiplexer.GetSubscriber();
        //    return sub.Publish(channel, message);
        //}

        ///// <summary>
        ///// 发布（使用序列化）
        ///// </summary>
        ///// <typeparam name="T"></typeparam>
        ///// <param name="channel"></param>
        ///// <param name="message"></param>
        ///// <returns></returns>
        //public long Publish<T>(RedisChannel channel, T message)
        //{
        //    var sub = _connMultiplexer.GetSubscriber();
        //    return sub.Publish(channel, Serialize(message!));
        //}

        //#endregion

        //#endregion






        /// <summary>
        /// 转换为字符串
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="list">数据列表</param>
        /// <returns>返回转为字符串后的数据列表</returns>
        private static IEnumerable<string> ConvertStrings<T>(IEnumerable<T> list) where T : struct
        {
            if (list == null) throw new ArgumentNullException(nameof(list));
            return list.Select(x => x.ToString())!;
        }


        /// <summary>
        /// 序列化（二进制）
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private static byte[]? Serialize(object obj)
        {
            if (obj == null)
            {
                return null;
            }


            var data = MessagePackSerializer.Serialize(obj);

            return data;
        }

        /// <summary>
        /// 序列化（二进制）
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private static T Deserialize<T>(byte[] data)
        {
            if (data == null)
            {
                return default!;
            }

            var obj = MessagePackSerializer.Deserialize<T>(data);
            return obj;
        }

        /// <summary>
        /// 序列化JSON
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        private static string SerializeJson<T>(T obj)
        {
            string tmp = string.Empty;
            if (obj != null)
            {
                tmp = JsonConvert.SerializeObject(obj);
            }
            return tmp;
        }

        /// <summary>
        /// 反序列化JSON
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="jsonStr"></param>
        /// <returns></returns>
        private static T DeserializeJson<T>(string jsonStr)
        {
            T tmp = default!;
            if (!string.IsNullOrWhiteSpace(jsonStr))
            {
                tmp = JsonConvert.DeserializeObject<T>(jsonStr)!;
            }
            return tmp;
        }

        #endregion
    }
}
