using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using dodohold.core;
using static dodohold.core.ZTOExpress.CreateOrderArgs;
using System.Net;
using System.Security.Cryptography;
using Spire.Pdf.Exporting.XPS.Schema;
using System.Xml.Linq;
using static QRCoder.PayloadGenerator;
using TencentCloud.Ssl.V20191205.Models;
using CSRedis;
using System.Data;
using TencentCloud.Omics.V20221128.Models;
using TencentCloud.Csip.V20221121.Models;
using COSXML.Network;
using System.Security.Policy;
using System.Diagnostics;


namespace molilian.core
{
    public partial class TkLogCore
    {

        public static bool save_dailys_log = false;

        public static string _test_oaid = "3B191CFA4C6B48F9BA459E915B57743BEC7D424979CC9C51BCAD0C245B1C7BA2";

        static TkLogCore()
        {
            int flag = RedisHelper.Get<int>("turn:save_dailys_log");
            if (flag == 1) save_dailys_log = true;
        }
        private static readonly SemaphoreSlim semaphore = new SemaphoreSlim(10, 10);

        public static async Task<int> BatchInsertLogDBAsync(int limit)
        {
            await semaphore.WaitAsync(); // 等待获取锁
            try
            {
                var result = await Task.Run(() =>
                {
                    return EndPointCore.ProcessEndPointNodes<int>(node =>
                    {
                        if (!node.is_public_api) return 0;

                        if (CenterHub.IsCenter)
                        {
                            if (node.is_coupon_api) return 0;
                        }
                        else
                        {
                            if (!node.is_coupon_api) return 0;
                        }

                        if (string.IsNullOrEmpty(node.redis_server)) return 0;


#if DEBUG
                        switch (node.name)
                        {

                            case "bj":
                                node.redis_server = "101.200.46.46:6379,password=pKBiS4ka2IpXayIdcx00,defaultDatabase=0,idleTimeout=20000,preheat=3,tryit=2,ssl=false,prefix=webhook";
                                break;
                            case "gz":
                                node.redis_server = "8.138.110.158:6379,password=pKBiS4ka2IpXayIdcx00,defaultDatabase=0,idleTimeout=20000,preheat=3,tryit=2,ssl=false,prefix=webhook";
                                break;
                            case "coupon1":
                                node.redis_server = "c1api.molilian.com:6379,password=pKBiS4ka2IpXayIdcx00,defaultDatabase=0,idleTimeout=20000,preheat=3,tryit=2,ssl=false,prefix=coupon";
                                break;
                            default: return 0;
                        }
#endif


                        var redis = RedisClientManager.GetRedisClient(node.redis_server);
                        return BatchInsertLogDB(limit, redis);
                    });
                });
                return result.Sum();
            }
            finally
            {
                semaphore.Release(); // 释放锁，允许下一个任务执行
            }
        }


        public static int BatchInsertLogDB2(int limit, CSRedisClient redis)
        {
            int total = 0;
            using var connection = DBContext.GetOpenConnection();
            connection.Open();
            using var transaction = connection.BeginTransaction();

            try
            {
                Stopwatch stopwatch = new Stopwatch(); // 创建一个计时器
                LoggerLibrary log = new LoggerLibrary("debug", "BatchInsertLogDB"); // 创建日志对象


                //第三方接口写入日志
                stopwatch.Start();
                int taskTotal = task_insert_tk_logs(limit, redis);
                total += taskTotal;
                stopwatch.Stop();
                log.Info($"task_insert_tk_logs 耗时: {stopwatch.ElapsedMilliseconds} ms,\t插入记录数: {taskTotal}");
                log.SaveAsync();
                stopwatch.Reset();


                stopwatch.Start();
                taskTotal = task_insert_parse_tb_logs(limit, redis);
                total += taskTotal;
                stopwatch.Stop();
                log.Info($"task_insert_parse_tb_logs 耗时: {stopwatch.ElapsedMilliseconds} ms,\t插入记录数: {taskTotal}");
                log.SaveAsync();
                stopwatch.Reset();

                stopwatch.Start();
                taskTotal = task_insert_parse_jd_logs(limit, redis);
                total += taskTotal;
                stopwatch.Stop();
                log.Info($"task_insert_parse_jd_logs 耗时: {stopwatch.ElapsedMilliseconds} ms,\t插入记录数: {taskTotal}");
                log.SaveAsync();
                stopwatch.Reset();

                stopwatch.Start();
                taskTotal = task_insert_parse_pdd_logs(limit, redis);
                total += taskTotal;
                stopwatch.Stop();
                log.Info($"task_insert_parse_pdd_logs 耗时: {stopwatch.ElapsedMilliseconds} ms,\t插入记录数: {taskTotal}");
                log.SaveAsync();
                stopwatch.Reset();

                stopwatch.Start();
                taskTotal = task_insert_parse_dy_logs(limit, redis);
                total += taskTotal;
                stopwatch.Stop();
                log.Info($"task_insert_parse_dy_logs 耗时: {stopwatch.ElapsedMilliseconds} ms,\t插入记录数: {taskTotal}");
                log.SaveAsync();
                stopwatch.Reset();

                stopwatch.Start();
                taskTotal = task_insert_parse_tool_logs(limit, redis);
                total += taskTotal;
                stopwatch.Stop();
                log.Info($"task_insert_parse_tool_logs 耗时: {stopwatch.ElapsedMilliseconds} ms,\t插入记录数: {taskTotal}");
                log.SaveAsync();
                stopwatch.Reset();

                stopwatch.Start();
                taskTotal = task_insert_parse_deeplink_logs(limit, redis);
                total += taskTotal;
                stopwatch.Stop();
                log.Info($"task_insert_parse_deeplink_logs  耗时: {stopwatch.ElapsedMilliseconds} ms,\t插入记录数: {taskTotal}");
                log.SaveAsync();
                stopwatch.Reset();

                stopwatch.Start();
                taskTotal = task_insert_parse_coupon_logs(limit, redis);
                total += taskTotal;
                stopwatch.Stop();
                log.Info($"task_insert_parse_coupon_logs 耗时: {stopwatch.ElapsedMilliseconds} ms,\t插入记录数: {taskTotal}");
                log.SaveAsync();
                stopwatch.Reset();

                stopwatch.Start();
                taskTotal = task_insert_parse_cps_logs(limit, redis);
                total += taskTotal;
                stopwatch.Stop();
                log.Info($"task_insert_parse_cps_logs 耗时: {stopwatch.ElapsedMilliseconds} ms,\t插入记录数: {taskTotal}");
                log.SaveAsync();
                stopwatch.Reset();

                stopwatch.Start();
                taskTotal = task_insert_promotion_img_logs(limit, redis);
                total += taskTotal;
                stopwatch.Stop();
                log.Info($"task_insert_promotion_img_logs 耗时: {stopwatch.ElapsedMilliseconds} ms,\t插入记录数: {taskTotal}");
                log.SaveAsync();
                stopwatch.Reset();

                stopwatch.Start();
                taskTotal = task_insert_parse_ks_logs(limit, redis);
                total += taskTotal;
                stopwatch.Stop();
                log.Info($"task_insert_parse_ks_logs 耗时: {stopwatch.ElapsedMilliseconds} ms,\t插入记录数: {taskTotal}");
                log.SaveAsync();
                stopwatch.Reset();

                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();

                _ = new LoggerLibrary("database_error", "parse_log")
                    .Info(ex.Message, ex.StackTrace)
                    .SaveAsync();

                NotifyCore.Notify(new NifyMessage
                {
                    message = $"【写入日志异常】\n{ex.Message}\n{ex.StackTrace}",
                    priority = NifyMessagePriority.high,
                    tags = ["red_circle"]
                });
            }
            finally
            {
                connection.Close();
            }
            return total;
        }

        public static int BatchInsertLogDB(int limit, CSRedisClient redis)
        {
            int total = 0;
            //using var connection = DBContext.GetOpenConnection();
            //connection.Open();
            //using var transaction = connection.BeginTransaction();
            using IDbTransaction transaction = null;
            using IDbConnection connection = null;

            try
            {
                Stopwatch stopwatch = new Stopwatch(); // 创建一个计时器

                var tasks = new List<Task<int>>
        {
            Task.Run(() => RunTaskWithLogging(() => task_insert_tk_logs(limit, redis), "task_insert_tk_logs")),
            Task.Run(() => RunTaskWithLogging(() => task_insert_parse_tb_logs(limit, redis), "task_insert_parse_tb_logs")),
            Task.Run(() => RunTaskWithLogging(() => task_insert_parse_jd_logs(limit, redis), "task_insert_parse_jd_logs")),
            Task.Run(() => RunTaskWithLogging(() => task_insert_parse_pdd_logs(limit, redis), "task_insert_parse_pdd_logs")),
            Task.Run(() => RunTaskWithLogging(() => task_insert_parse_dy_logs(limit, redis), "task_insert_parse_dy_logs")),
            Task.Run(() => RunTaskWithLogging(() => task_insert_parse_tool_logs(limit, redis), "task_insert_parse_tool_logs")),
            Task.Run(() => RunTaskWithLogging(() => task_insert_parse_deeplink_logs(limit, redis), "task_insert_parse_deeplink_logs")),
            Task.Run(() => RunTaskWithLogging(() => task_insert_parse_coupon_logs(limit, redis), "task_insert_parse_coupon_logs")),
            Task.Run(() => RunTaskWithLogging(() => task_insert_parse_cps_logs(limit, redis), "task_insert_parse_cps_logs")),
            Task.Run(() => RunTaskWithLogging(() => task_insert_promotion_img_logs(limit, redis), "task_insert_promotion_img_logs")),
            Task.Run(() => RunTaskWithLogging(() => task_insert_parse_ks_logs(limit, redis), "task_insert_parse_ks_logs"))
        };

                // 等待所有任务完成
                Task.WhenAll(tasks).Wait();//252行

                // 计算所有任务的结果总和
                total = tasks.Select(t => t.Result).Sum();

                //transaction.Commit();
            }
            catch (Exception ex)
            {
                //transaction.Rollback();


                // 构建异常详细信息字符串
                string detailedError = $"{ex.Message}\n" +
                                       $"堆栈跟踪: {ex.StackTrace}\n";

                if (ex.InnerException != null)
                {
                    detailedError += $"内部异常: {ex.InnerException.Message}\n" +
                                     $"内部堆栈跟踪: {ex.InnerException.StackTrace}\n";
                }

                // 如果异常包含其他数据，也可以记录下来
                if (ex.Data != null && ex.Data.Count > 0)
                {
                    detailedError += "附加数据:\n";
                    foreach (var key in ex.Data.Keys)
                    {
                        detailedError += $"{key}: {ex.Data[key]}\n";
                    }
                }


                _ = new LoggerLibrary("database_error", "parse_log")
                    .Info(detailedError)
                    .SaveAsync();


                NotifyCore.Notify(new NifyMessage
                {
                    message = $"【Exception】\n{detailedError}",
                    priority = NifyMessagePriority.high,
                    tags = ["red_circle"]
                });
            }
            finally
            {
                //connection.Close();
            }
            return total;
        }


        // 新增一个辅助方法来处理日志记录和任务执行
        private static int RunTaskWithLogging(Func<int> taskFunc, string taskName)
        {
            LoggerLibrary log = new LoggerLibrary("debug", "BatchInsertLogDB"); // 创建日志对象
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            int taskTotal = taskFunc();
            stopwatch.Stop();
            log.Info($"{taskName} 耗时: {stopwatch.ElapsedMilliseconds} ms,\t插入记录数: {taskTotal}");
            log.SaveAsync();
            return taskTotal;
        }


        public static int BatchInsertLogDB(int limit)
        {
            var result = EndPointCore.ProcessEndPointNodes<int>(node =>
            {
                if (!node.is_public_api) return 0;

                if (CenterHub.IsCenter)
                {
                    if (node.is_coupon_api) return 0;
                }
                else
                {
                    if (!node.is_coupon_api) return 0;
                }

                if (string.IsNullOrEmpty(node.redis_server)) return 0;

                var redis = RedisClientManager.GetRedisClient(node.redis_server);
                return BatchInsertLogDB(limit, redis);
            });
            return result.Sum();
        }
        private static void saveCache(string channel, int accountId, string accountName, bool success, string message, string reason)
        {
            saveAccountCache("all", success, message, reason);
            saveAccountCache($"{channel}", success, message, reason);
            saveAccountCache($"{accountName}", success, message, reason);
            if (accountId != 0)
            {
                //todo 放着跑两天，要将读取的地方改成读取accountid
                saveAccountCache($"{channel}_{accountId}", success, message, reason);
            }
        }

        private static void saveAccountCache(string accountName, bool success, string message, string reason)
        {
            RedisHelper.IncrBy($":total:{accountName}:{DateTime.Now:yyyyMM}");
            RedisHelper.IncrBy($":total:{accountName}:{DateTime.Now:yyyyMMdd}");
            RedisHelper.IncrBy($":total:{accountName}:{DateTime.Now:yyyyMMddHH}");


            string result = success ? "success" : "fail";
            RedisHelper.IncrBy($":total:{accountName}:{result}:{DateTime.Now:yyyyMM}");
            RedisHelper.IncrBy($":total:{accountName}:{result}:{DateTime.Now:yyyyMMdd}");
            RedisHelper.IncrBy($":total:{accountName}:{result}:{DateTime.Now:yyyyMMddHH}");


            if (!string.IsNullOrEmpty(message))
            {
                RedisHelper.SAdd($":total:{accountName}:message:{DateTime.Now:yyyyMM}", message);
                RedisHelper.SAdd($":total:{accountName}:message:{DateTime.Now:yyyyMMdd}", message);
                RedisHelper.SAdd($":total:{accountName}:message:{DateTime.Now:yyyyMMddHH}", message);

                RedisHelper.IncrBy($":total:{accountName}:{message}:{DateTime.Now:yyyyMM}");
                RedisHelper.IncrBy($":total:{accountName}:{message}:{DateTime.Now:yyyyMMdd}");
                RedisHelper.IncrBy($":total:{accountName}:{message}:{DateTime.Now:yyyyMMddHH}");

                RedisHelper.IncrBy($":total:{accountName}:message:{message}:{DateTime.Now:yyyyMM}");
                RedisHelper.IncrBy($":total:{accountName}:message:{message}:{DateTime.Now:yyyyMMdd}");
                RedisHelper.IncrBy($":total:{accountName}:message:{message}:{DateTime.Now:yyyyMMddHH}");
            }

            if (!string.IsNullOrEmpty(reason))
            {
                RedisHelper.SAdd($":total:{accountName}:reason:{DateTime.Now:yyyyMM}", reason);
                RedisHelper.SAdd($":total:{accountName}:reason:{DateTime.Now:yyyyMMdd}", reason);
                RedisHelper.SAdd($":total:{accountName}:reason:{DateTime.Now:yyyyMMddHH}", reason);

                RedisHelper.IncrBy($":total:{accountName}:{reason}:{DateTime.Now:yyyyMM}");
                RedisHelper.IncrBy($":total:{accountName}:{reason}:{DateTime.Now:yyyyMMdd}");
                RedisHelper.IncrBy($":total:{accountName}:{reason}:{DateTime.Now:yyyyMMddHH}");


                RedisHelper.IncrBy($":total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMM}");
                RedisHelper.IncrBy($":total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMdd}");
                RedisHelper.IncrBy($":total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMddHH}");
            }

        }

        private static async Task saveUnionCouponParseCacheAsync(TkDataDTO data)
        {
            string cacheKey = $":cache:parse:{data.ip}_{data.oaid}_{data.itemId}";
            await EndPointCore.ProcessEndPointNodesAsync(node =>
            {
                if (!node.is_coupon_api) return Task.CompletedTask;
                if (string.IsNullOrEmpty(node.redis_server)) return Task.CompletedTask;

                var redis = RedisClientManager.GetRedisClient(node.redis_server);
                redis.Set(cacheKey, 1, 2 * 86400);
                return Task.CompletedTask;
            });
        }
        private static void saveClientRequestTotal(TkChannelEnum channel, string ip, string oaid)
        {
            string cacheKey = $":cache:{channel}:ip:{DateTime.Now:yyyyMMdd}:{ip}";
            RedisHelper.IncrBy(cacheKey);
            RedisHelper.Expire(cacheKey, 86400);

            if (!string.IsNullOrEmpty(oaid))
            {
                cacheKey = $":cache:{channel}:oaid:{DateTime.Now:yyyyMMdd}:{oaid}";
                RedisHelper.IncrBy(cacheKey);
                RedisHelper.Expire(cacheKey, 86400);
            }
        }
        private static void saveClientRequestTotal(string channel, string ip, string oaid)
        {
            string cacheKey = $":cache:{channel}:ip:{DateTime.Now:yyyyMMdd}:{ip}";
            RedisHelper.IncrBy(cacheKey);
            RedisHelper.Expire(cacheKey, 86400);

            if (!string.IsNullOrEmpty(oaid))
            {
                cacheKey = $":cache:{channel}:oaid:{DateTime.Now:yyyyMMdd}:{oaid}";
                RedisHelper.IncrBy(cacheKey);
                RedisHelper.Expire(cacheKey, 86400);
            }
        }
        public static int getClientRequestTotalByOAID(TkChannelEnum channel, string oaid)
        {
            if (string.IsNullOrEmpty(oaid)) return 0;
            string cacheKey = $":cache:{channel}:oaid:{DateTime.Now:yyyyMMdd}:{oaid}";
            return RedisHelper.Get<int>(cacheKey);
        }
        public static int getClientRequestTotalByIp(TkChannelEnum channel, string ip)
        {
            if (string.IsNullOrEmpty(ip)) return 0;
            string cacheKey = $":cache:{channel}:ip:{DateTime.Now:yyyyMMdd}:{ip}";
            return RedisHelper.Get<int>(cacheKey);
        }
        public static int getClientRequestTotalByOAID(string channel, string oaid)
        {
            if (string.IsNullOrEmpty(oaid)) return 0;
            string cacheKey = $":cache:{channel}:oaid:{DateTime.Now:yyyyMMdd}:{oaid}";
            return RedisHelper.Get<int>(cacheKey);
        }
        public static int getClientRequestTotalByIp(string channel, string ip)
        {
            if (string.IsNullOrEmpty(ip)) return 0;
            string cacheKey = $":cache:{channel}:ip:{DateTime.Now:yyyyMMdd}:{ip}";
            return RedisHelper.Get<int>(cacheKey);
        }


        private static void saveClientRequestTotal(CpsChannelEnum channel, string ip, string oaid)
        {
            string cacheKey = $":cache:cps_{channel}:ip:{DateTime.Now:yyyyMMdd}:{ip}";
            RedisHelper.IncrBy(cacheKey);
            RedisHelper.Expire(cacheKey, 86400);

            if (!string.IsNullOrEmpty(oaid))
            {
                cacheKey = $":cache:cps_{channel}:oaid:{DateTime.Now:yyyyMMdd}:{oaid}";
                RedisHelper.IncrBy(cacheKey);
                RedisHelper.Expire(cacheKey, 86400);
            }
        }
        public static int getClientRequestTotalByOAID(CpsChannelEnum channel, string oaid)
        {
            if (string.IsNullOrEmpty(oaid)) return 0;
            string cacheKey = $":cache:cps_{channel}:oaid:{DateTime.Now:yyyyMMdd}:{oaid}";
            return RedisHelper.Get<int>(cacheKey);
        }
        public static int getClientRequestTotalByIp(CpsChannelEnum channel, string ip)
        {
            if (string.IsNullOrEmpty(ip)) return 0;
            string cacheKey = $":cache:cps_{channel}:ip:{DateTime.Now:yyyyMMdd}:{ip}";
            return RedisHelper.Get<int>(cacheKey);
        }





        private static void saveParseCache(string channel, int accountId, string accountName,
            bool success, string message, string reason, string deeplink)
        {
            string dp_flag = deeplink switch
            {
                "" => "none",
                "tbopen://m.taobao.com/tbopen/index.html" or
                "pinduoduo://com.xunmeng.pinduoduo/" or
                "snssdk1128://feed?refer=web" or
                "bdnetdisk://n/action.EXTERNAL_ACTIVITY" or
                "openapp.jdmobile://virtual?params=" or "openapp.jdmobile://" => "home",
                _ => success ? "success" : "fail",
            };

            //关于dp的缓存
            saveParseAccountCache($"dp_{dp_flag}:all", success, message, reason);
            saveParseAccountCache($"dp_{dp_flag}:{channel}", success, message, reason);
            saveParseAccountCache($"dp_{dp_flag}:{accountName}", success, message, reason);
            if (accountId != 0)
            {
                saveParseAccountCache($"dp_{dp_flag}:{channel}_{accountId}", success, message, reason);
            }

            saveParseAccountCache("all", success, message, reason);
            saveParseAccountCache($"{channel}", success, message, reason);
            saveParseAccountCache($"{accountName}", success, message, reason);
            if (accountId != 0)
            {
                //todo 放着跑两天，要将读取的地方改成读取accountid
                saveParseAccountCache($"{channel}_{accountId}", success, message, reason);
            }
        }


        private static void saveParseAccountCache(string accountName, bool success,
            string message, string reason)
        {

            RedisHelper.IncrBy($":parse_total:{accountName}:{DateTime.Now:yyyyMM}");
            RedisHelper.IncrBy($":parse_total:{accountName}:{DateTime.Now:yyyyMMdd}");
            RedisHelper.IncrBy($":parse_total:{accountName}:{DateTime.Now:yyyyMMddHH}");


            string result = success ? "success" : "fail";
            RedisHelper.IncrBy($":parse_total:{accountName}:{result}:{DateTime.Now:yyyyMM}");
            RedisHelper.IncrBy($":parse_total:{accountName}:{result}:{DateTime.Now:yyyyMMdd}");
            RedisHelper.IncrBy($":parse_total:{accountName}:{result}:{DateTime.Now:yyyyMMddHH}");


            if (!string.IsNullOrEmpty(message))
            {
                RedisHelper.SAdd($":parse_total:{accountName}:message:{DateTime.Now:yyyyMM}", message);
                RedisHelper.SAdd($":parse_total:{accountName}:message:{DateTime.Now:yyyyMMdd}", message);
                RedisHelper.SAdd($":parse_total:{accountName}:message:{DateTime.Now:yyyyMMddHH}", message);

                RedisHelper.IncrBy($":parse_total:{accountName}:{message}:{DateTime.Now:yyyyMM}");
                RedisHelper.IncrBy($":parse_total:{accountName}:{message}:{DateTime.Now:yyyyMMdd}");
                RedisHelper.IncrBy($":parse_total:{accountName}:{message}:{DateTime.Now:yyyyMMddHH}");
                RedisHelper.IncrBy($":parse_total:{accountName}:message:{message}:{DateTime.Now:yyyyMM}");
                RedisHelper.IncrBy($":parse_total:{accountName}:message:{message}:{DateTime.Now:yyyyMMdd}");
                RedisHelper.IncrBy($":parse_total:{accountName}:message:{message}:{DateTime.Now:yyyyMMddHH}");
            }

            if (!string.IsNullOrEmpty(reason))
            {
                RedisHelper.SAdd($":parse_total:{accountName}:reason:{DateTime.Now:yyyyMM}", reason);
                RedisHelper.SAdd($":parse_total:{accountName}:reason:{DateTime.Now:yyyyMMdd}", reason);
                RedisHelper.SAdd($":parse_total:{accountName}:reason:{DateTime.Now:yyyyMMddHH}", reason);

                RedisHelper.IncrBy($":parse_total:{accountName}:{reason}:{DateTime.Now:yyyyMM}");
                RedisHelper.IncrBy($":parse_total:{accountName}:{reason}:{DateTime.Now:yyyyMMdd}");
                RedisHelper.IncrBy($":parse_total:{accountName}:{reason}:{DateTime.Now:yyyyMMddHH}");

                RedisHelper.IncrBy($":parse_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMM}");
                RedisHelper.IncrBy($":parse_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMdd}");
                RedisHelper.IncrBy($":parse_total:{accountName}:reason:{reason}:{DateTime.Now:yyyyMMddHH}");
            }
        }

        public static int GetTotal(string keyname, bool all_node = true)
        {
            //:coupon_total:tb:20240706
            //:coupon_total:tb:success:20240706
            //:coupon_total:tb:放弃转链:20240706

            var result = EndPointCore.ProcessEndPointNodes<int>(node =>
            {
                if (!node.is_public_api) return 0;
                if (string.IsNullOrEmpty(node.redis_server)) return 0;

                if (!all_node)
                {
                    if (CenterHub.IsCenter)
                    {
                        if (node.is_coupon_api) { return 0; }
                    }
                    else
                    {
                        if (!node.is_coupon_api) { return 0; }
                    }
                }

#if DEBUG
                switch (node.name)
                {

                    case "bj":
                        node.redis_server = "101.200.46.46:6379,password=pKBiS4ka2IpXayIdcx00,defaultDatabase=0,idleTimeout=20000,preheat=3,tryit=2,ssl=false,prefix=webhook";
                        break;
                    case "gz":
                        node.redis_server = "8.138.110.158:6379,password=pKBiS4ka2IpXayIdcx00,defaultDatabase=0,idleTimeout=20000,preheat=3,tryit=2,ssl=false,prefix=webhook";
                        break;
                    case "coupon1":
                        node.redis_server = "c1api.molilian.com:6379,password=pKBiS4ka2IpXayIdcx00,defaultDatabase=0,idleTimeout=20000,preheat=3,tryit=2,ssl=false,prefix=coupon";
                        break;
                    default: return 0;
                }

#endif
                var redis = RedisClientManager.GetRedisClient(node.redis_server);
                int count = redis.Get<int>(keyname);
                return count;
            });
            return result.Sum();
        }

        public static string[] GetTotalKeys(string keyname, bool all_node = true)
        {

            var result = EndPointCore.ProcessEndPointNodes<string[]>(node =>
            {
                if (!node.is_public_api) return [];
                if (string.IsNullOrEmpty(node.redis_server)) return [];

                if (!all_node)
                {
                    if (CenterHub.IsCenter)
                    {
                        if (node.is_coupon_api) { return []; }
                    }
                    else
                    {
                        if (!node.is_coupon_api) { return []; }
                    }
                }
#if DEBUG
                switch (node.name)
                {

                    case "bj":
                        node.redis_server = "101.200.46.46:6379,password=pKBiS4ka2IpXayIdcx00,defaultDatabase=0,idleTimeout=20000,preheat=3,tryit=2,ssl=false,prefix=webhook";
                        break;
                    case "gz":
                        node.redis_server = "8.138.110.158:6379,password=pKBiS4ka2IpXayIdcx00,defaultDatabase=0,idleTimeout=20000,preheat=3,tryit=2,ssl=false,prefix=webhook";
                        break;
                    case "coupon1":
                        node.redis_server = "c1api.molilian.com:6379,password=pKBiS4ka2IpXayIdcx00,defaultDatabase=0,idleTimeout=20000,preheat=3,tryit=2,ssl=false,prefix=coupon";
                        break;
                    default: return [];
                }
#endif

                var redis = RedisClientManager.GetRedisClient(node.redis_server);

                string[] message_keys = redis.SMembers(keyname);
                return message_keys;
            });

            string[] message_keys = [];
            foreach (var arr in result)
            {
                message_keys = message_keys.Union(arr).ToArray();
            }
            return message_keys;
        }


    }

}
