using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.AspNetCore.Mvc.Formatters;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using MS.Entities.AccountingService_Models;
using System.Collections.Concurrent;
using Newtonsoft.Json;

namespace MS.WebCore.Core
{
    public class RedisExample
    {
        private static ConnectionMultiplexer redisConnection;
        private static IDatabase redisDb;
        //string connectionString = "localhost,password=DFS2024@,db=0,connectTimeout=5000";
        //string connectionString = "localhost,password=DFS2024@";

        public RedisExample(int dbIndex = 0)
        {
            //string connectionString = $"localhost,db={dbIndex},connectTimeout=5000";
            //redisConnection = ConnectionMultiplexer.Connect(connectionString);
            redisConnection = ConnectionMultiplexer.Connect("localhost");
            redisDb = redisConnection.GetDatabase();
        }

        public void SetData(string key, string value)
        {
            redisDb.StringSet(key, value);
        }

        public string GetData(string key)
        {
            return redisDb.StringGet(key);
        }

        public void DeleteData(string key, string field)
        {
            redisDb.HashDelete(key, field);
            //redisDb.KeyDelete(key);
        }
        public void DeleteData(string key)
        {
            redisDb.KeyDelete(key);
            //redisDb.KeyDelete(key);
        }
        public  bool HashKeyExists(string hashKey, string fieldKey)
        {
            return redisDb.HashExists(hashKey, fieldKey);
        }
        public void SetDataWithTime(string key, string value, DateTime time)
        {
            redisDb.SortedSetAdd("mySortedSet", value, time.Ticks);
        }
        public string GetValueByTime(DateTime time)
        {
            var result = redisDb.SortedSetRangeByScore("mySortedSet", time.Ticks, time.Ticks);
            return result.FirstOrDefault();
        }

        public void AddToHash(string key, string field, string value)
        {
            RedisType keyType = redisDb.KeyType(key);
            if (keyType != RedisType.None && keyType != RedisType.Hash)
            {
                // throw new Exception("Key is not of type Hash");
            }

            redisDb.HashSet(key, field, value);
        }


        //public List<string> GetListValues()
        //{
        //    var values = redisDb.ListRange("myList");

        //    List<string> result = new List<string>();
        //    foreach (var value in values)
        //    {
        //        result.Add(value.ToString());
        //    }

        //    return result;
        //}

        public List<string> GetValuesByUUID(string uuid)
        {
            var values = redisDb.ListRange("myList");
            List<string> result = new List<string>();

            foreach (var value in values)
            {
                var parts = value.ToString().Split(new[] { ' ' }, 2);
                var storedUUID = parts[0];

                if (storedUUID == uuid)
                {
                    result.Add(value.ToString());
                }
            }

            return result;
        }


        public List<KeyValuePair<string, string>> GetListValues()
        {
            var values = redisDb.HashGetAll("myList");

            List<KeyValuePair<string, string>> result = new List<KeyValuePair<string, string>>();
            foreach (var value in values)
            {
                result.Add(new KeyValuePair<string, string>(value.Name, value.Value));
            }

            return result;
        }

        public List<KeyValuePair<string, string>> GetValuesByKey(string key)
        {
            var values = redisDb.HashGetAll("myList");
            List<KeyValuePair<string, string>> result = new List<KeyValuePair<string, string>>();

            foreach (var value in values)
            {
                if (value.Name == key)
                {
                    result.Add(new KeyValuePair<string, string>(value.Name, value.Value));
                }
            }

            return result;
        }
        public  List<string> GetListFromRedis(string listKey)
        {
            var redisValues = redisDb.ListRange(listKey);
            return redisValues.Select(value => value.ToString()).ToList();
        }

        public void AddToList(string key, string value)
        {
            RedisType keyType = redisDb.KeyType(key);
            if (keyType != RedisType.None && keyType != RedisType.Hash)
            {
                //
                //throw new Exception("Key is not of type Hash");
            }

            redisDb.HashSet(key, value, value);
        }

        public List<KeyValuePair<string, string>> GetListValues(string key)
        {
            RedisType keyType = redisDb.KeyType(key);
            if (keyType != RedisType.Hash)
            {
                // throw new Exception("Key is not of type Hash");
            }

            var values = redisDb.HashGetAll(key);

            List<KeyValuePair<string, string>> result = new List<KeyValuePair<string, string>>();
            foreach (var value in values)
            {
                result.Add(new KeyValuePair<string, string>(value.Name, value.Value));
            }

            return result;
        }
        public List<string> GetHashKeysByPattern(string pattern)
        {
            List<string> keys = new List<string>();

            // 使用服务器的 EndPoint 获取服务器的键
            EndPoint[] endPoints = redisDb.Multiplexer.GetEndPoints();
            foreach (EndPoint endPoint in endPoints)
            {
                IServer server = redisDb.Multiplexer.GetServer(endPoint);
                keys.AddRange(server.Keys(pattern: pattern, database: redisDb.Database).Select(key => (string)key));
            }

            return keys;
        }
        public  bool SetHashField(string hashKey, string fieldKey, string value)
        {
            // 获取数据库（默认是0）  

            // 使用HashSet方法来更改哈希中字段的值  
            // 注意：HashSet方法返回bool值，表示操作是否成功  
            return redisDb.HashSet(hashKey, fieldKey, value);
        }
        public Dictionary<string, string> GetHashAll(string key)
        {
            HashEntry[] entries = redisDb.HashGetAll(key);
            var result = new Dictionary<string, string>();
            foreach (var entry in entries)
            {
                result.Add(entry.Name.ToString(), entry.Value.ToString());
            }
            return result;
        }
        /// <summary>
        /// 根据key获取hash列表所有数据
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public List<UserIdAndName> GetAllUsersOptimized(string key)
        {
            var allEntries = redisDb.HashGetAll(key);

            var result = new List<UserIdAndName>(allEntries.Length);

            var tempList = new UserIdAndName[allEntries.Length];
            int count = 0;

            for (int i = 0; i < allEntries.Length; i++)
            {
                if (!allEntries[i].Value.IsNullOrEmpty)
                {
                    var user = ParseUser(allEntries[i].Value.ToString());
                    if (user != null)
                    {
                        tempList[count] = user;
                        count++;
                    }
                }
            }

            result.AddRange(tempList.Take(count));
            return result;
        }
        public List<UserIdAndName> GetUsersSimplePagedParallel(string key)
        {
            var allEntries = redisDb.HashGetAll(key);
            var result = new ConcurrentBag<UserIdAndName>();

            Parallel.ForEach(allEntries, entry =>
            {
                if (!entry.Value.IsNullOrEmpty)
                {
                    var user = ParseUser(entry.Value.ToString());
                    if (user != null) result.Add(user);
                }
            });

            return new List<UserIdAndName>(result);
        }

        private UserIdAndName ParseUser(string input)
        {
            if (string.IsNullOrEmpty(input)) return null;

            UserIdAndName rootObject = JsonConvert.DeserializeObject<UserIdAndName>(input);

            return rootObject;
        }
    }
}
