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;


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;
        }
        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();
        }

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

            try
            {
                //第三方接口写入日志
                total += task_insert_tk_logs(connection, transaction, limit, redis);

                total += task_insert_parse_tb_logs(connection, transaction, limit, redis);

                total += task_insert_parse_jd_logs(connection, transaction, limit, redis);

                total += task_insert_parse_pdd_logs(connection, transaction, limit, redis);

                total += task_insert_parse_dy_logs(connection, transaction, limit, redis);

                total += task_insert_parse_tool_logs(connection, transaction, limit, redis);

                total += task_insert_parse_deeplink_logs(connection, transaction, limit, redis);

                total += task_insert_parse_coupon_logs(connection, transaction, limit, redis);

                total += task_insert_parse_cps_logs(connection, transaction, limit, redis);

                total += task_insert_promotion_img_logs(connection, transaction, limit, redis);


                total += task_insert_parse_ks_logs(connection, transaction, limit, redis);

                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;
        }

        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;
        }


    }

}
