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 Dataoke;
using Google.Protobuf.WellKnownTypes;
using System.Xml.Linq;
using Mysqlx.Crud;
using ZstdSharp.Unsafe;
using YunhuiKit;


namespace molilian.core
{

    public partial class JdPoolCore
    {
        public enum JdAction
        {
            all,
            api,
            parse,
            coupon,
            promotionQuery
        }
        private static string _end_point;
        private static Dictionary<string, decimal> _incomeAmt = new();
        static JdPoolCore()
        {
            _end_point = Environment.GetEnvironmentVariable("EndPoint");
        }

        private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);

        private static IEnumerable<JdPoolDTO> _cached;
        private static IEnumerable<JdPoolDTO> _all_cached;
        public static async Task<JdPoolDTO?> GetOneAsync()
        {
            var list = await ListAsync();
            if (!list.Any()) return null;
            return list.OrderBy(l => Guid.NewGuid()).FirstOrDefault();
        }

        public static async Task<JdPoolDTO?> GetSpecialOneAsync(int accountid)
        {
            var list = await AllListAsync();
            if (!list.Any()) return null;
            return list.Where(e => e.id == accountid).OrderBy(l => Guid.NewGuid()).FirstOrDefault();
        }


        public static async Task<JdPoolDTO?> GetOneAsync(int id, JdAction action)
        {
            var list = await ListAsync();
            if (!list.Any()) return null;

            var eligibleItems = new List<JdPoolDTO>();
            foreach (var item in list.Where(e => e.id == id))
            {
                if (await IsNotExceedDailyIncomeLimitAsync(item, action))
                {
                    eligibleItems.Add(item);
                }
            }

            return eligibleItems.OrderBy(l => Guid.NewGuid()).FirstOrDefault();
        }

        public static async Task<JdPoolDTO?> GetOneAsync(JdAction action, bool is_numeric, UnionParseRequest request)
        {
            var list = await ListAsync();
            if (!list.Any()) return null;

            if (!string.IsNullOrEmpty(request.Type))
            {
                list = list.Where(item => request.Type.Equals(item.parse_type)).ToList();
                if (!list.Any()) return null;
            }
            else
            {
                if (!string.IsNullOrEmpty(request.RiskStrategy) && !"os".Equals(request.RiskStrategy) && request.LaunchScene != -1)
                {
                    list = list.Where(item => string.IsNullOrEmpty(item.parse_type) && request.RiskStrategy.Equals(item.riskStrategy) && item.launchScene == request.LaunchScene).ToList();
                    if (!list.Any()) return null;
                }
                else
                {
                    list = list.Where(item => string.IsNullOrEmpty(item.parse_type) && string.IsNullOrEmpty(item.riskStrategy)).ToList();
                    if (!list.Any()) return null;
                }

            }

            var eligibleItems = new List<JdPoolDTO>();
            foreach (var item in list)
            {
                if (await IsNotExceedDailyIncomeLimitAsync(item, action))
                {
                    // 如果 is_numeric 为 true，则排除 work_mode = Ddx (4) 的记录
                    if (is_numeric == true && item.work_mode == JdUnionWorkMode.Ddx)
                        continue;
                    eligibleItems.Add(item);
                }
            }

            return eligibleItems.OrderBy(l => Guid.NewGuid()).FirstOrDefault();
        }


        private static async Task<bool> IsNotExceedDailyIncomeLimitAsync(JdPoolDTO item, JdAction action)
        {
            if (!string.IsNullOrEmpty(_end_point) && !string.IsNullOrEmpty(item.end_point))
            {
                if (item.end_point != _end_point) return false;
            }
            switch (action)
            {
                case JdAction.api:
                    if (item.work_mode != JdUnionWorkMode.SiteApi) return false;
                    break;
                case JdAction.parse:
                    if (!item.enable_parse) return false;
                    break;
                case JdAction.coupon:
                    if (!item.enable_coupon) return false;
                    break;
            }

            // 使用初始化参数创建工作时间表
            if (!new WorkSchedule(item.time_range).IsWorkHour()) return false;

            if (item.daily_calls_limit > 0)
            {
                int daily_num = RiskControlCore.GetCalls(TkChannelEnum.jd, item.id, DateTime.Now.ToString("yyyyMMdd"));
                if (daily_num >= item.daily_calls_limit) return false;
            }
            if (item.hourly_calls_limit > 0)
            {
                int hourly_num = RiskControlCore.GetCalls(TkChannelEnum.jd, item.id, DateTime.Now.ToString("yyyyMMddHH"));
                if (hourly_num >= item.hourly_calls_limit) return false;
            }
            return true;
        }


        public static async Task<IEnumerable<JdPoolDTO>> AllListAsync(bool force = false)
        {
            if (!force && _all_cached != default) return _all_cached;

            try
            {
                await _semaphore.WaitAsync();

                string cache_key = $"cache:all_jd_pool";
                var list = await RedisKit.GetAsync<IEnumerable<JdPoolDTO>>(cache_key);

                if (force || list == default)
                {
                    list = new DBContext.Table("jd_pool").Select<JdPoolDTO>();
                    if (list == null) return default;

                    // 等待 Redis 写入完成
                    await RedisKit.SetAsync(cache_key, list, 30 * 86400);
                }

                _all_cached = list;
                return list;
            }
            catch (Exception)
            {
                // 发生异常时返回上一次的缓存，如果没有则返回默认值
                return _all_cached ?? default;
            }
            finally
            {
                _semaphore.Release();
            }
        }

        public static async Task<IEnumerable<JdPoolDTO>> ListAsync(bool force = false)
        {
            if (!force && _cached != null) return _cached;
            try
            {
                await _semaphore.WaitAsync();

                // 如果缓存存在且未强制刷新，直接返回
                if (!force && _cached != null) return _cached;

                string cache_key = $"cache:jd_pool";
                IEnumerable<JdPoolDTO>? list = null;

                // 尝试从Redis获取数据
                try
                {
                    list = await RedisKit.GetAsync<IEnumerable<JdPoolDTO>>(cache_key);
                }
                catch (Exception ex)
                {
                    // 记录Redis错误
                    _ = new LoggerLibrary("JdPool", "Redis").Info(ex.Message, ex.StackTrace).SaveAsync();
                }

                // 如果Redis获取失败或需要强制刷新
                if (force || list == null)
                {
                    try
                    {
                        list = new DBContext.Table("jd_pool")
                            .Where("status=@status", new { status = 1 })
                            .Select<JdPoolDTO>();

                        if (list != null && list.Any())
                        {
                            // 更新计数器
                            foreach (var item in list)
                            {
                                try
                                {
                                    await RiskControlCore.SetCallsAsync(TkChannelEnum.jd, item.id,
                                        DateTime.Now.ToString("yyyyMMddHH"), item.current_hourly_calls);
                                    await RiskControlCore.SetCallsAsync(TkChannelEnum.jd, item.id,
                                        DateTime.Now.ToString("yyyyMMdd"), item.current_daily_calls);
                                }
                                catch (Exception ex)
                                {
                                    // 记录计数器更新错误
                                    _ = new LoggerLibrary("JdPool", "Counter").Info(ex.Message, ex.StackTrace).SaveAsync();
                                }
                            }

                            // 尝试更新Redis缓存
                            try
                            {
                                await RedisKit.SetAsync(cache_key, list, 30 * 86400);
                            }
                            catch (Exception ex)
                            {
                                // 记录Redis更新错误
                                _ = new LoggerLibrary("JdPool", "Redis").Info(ex.Message, ex.StackTrace).SaveAsync();
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        // 记录数据库查询错误
                        _ = new LoggerLibrary("JdPool", "Database").Info(ex.Message, ex.StackTrace).SaveAsync();

                        // 如果数据库查询失败但缓存还在，继续使用缓存
                        if (_cached != null) return _cached;
                        throw; // 如果没有任何可用数据，则抛出异常
                    }
                }
                _cached = list;
                return list ?? [];
            }
            finally
            {
                _semaphore.Release();
            }
        }

        public static void Refresh()
        {
            _all_cached = null;
            _cached = null;
            _ = ListAsync(true);
            _ = AllListAsync(true);
        }

        public static int Update(JdPoolDTO account)
        {
            return new DBContext.Table("jd_pool")
                .Add("current_hourly_calls", account.current_hourly_calls)
                .Add("current_daily_calls", account.current_daily_calls)

                .Add("today_clickNum", account.today_clickNum)
                .Add("today_cosFee", account.today_cosFee)
                .Add("today_cosPrice", account.today_cosPrice)
                .Add("today_finishCosFee", account.today_finishCosFee)
                .Add("today_finishCosPrice", account.today_finishCosPrice)
                .Add("today_finishOrderNum", account.today_finishOrderNum)
                .Add("today_orderNum", account.today_orderNum)
                .Where("id=@id", new { account.id })
                .Update();
        }



        public static int UpdateCookies(string cookies, string union_cookies, string user_agent, string h5st, string envStr)
        {
            if (string.IsNullOrEmpty(cookies)) return 0;
            string pin = cookies.GetContentPart("pin=", ";");
            pin = pin.UrlDecode();

            string company = pin;
            int accountId = 0;
            if (string.IsNullOrEmpty(pin)) return 0;
            var exist = new DBContext.Table("jd_pool").Get<JdPoolDTO>("pin=@pin", new { pin });
            if (exist != null)
            {
                var status = exist.status;
                var work_mode = exist.work_mode;
                accountId = exist.id;
                if (work_mode == JdUnionWorkMode.Crawler) status = true;
                var update = new DBContext.Table("jd_pool")
                    .Add("pin", pin)
                    .Add("cookies", cookies)
                    .Add("union_cookies", union_cookies)
                    .Add("status", status)
                    .Add("last_time", DateTime.Now)
                    .Add("login_time", DateTime.Now)
                    .Where("pin=@pin", new { pin });
                if (!string.IsNullOrEmpty(user_agent)) update.Add("user_agent", user_agent);
                if (!string.IsNullOrEmpty(h5st)) update.Add("h5st", h5st);
                if (!string.IsNullOrEmpty(envStr)) update.Add("envStr", envStr);

                update.Update();
                if (status) _ = ListAsync(true);
            }
            else
            {
                var update = new DBContext.Table("jd_pool")
                    .Add("pin", pin)
                    .Add("name", pin)
                    .Add("company", pin)
                    .Add("description", "由cookies上报创建此记录")
                    .Add("cookies", cookies)
                    .Add("union_cookies", union_cookies)
                    .Add("create_time", DateTime.Now)
                    .Add("last_time", DateTime.Now)
                    .Add("login_time", DateTime.Now)
                    .Add("status", 0);
                if (!string.IsNullOrEmpty(user_agent)) update.Add("user_agent", user_agent);
                if (!string.IsNullOrEmpty(h5st)) update.Add("h5st", h5st);
                if (!string.IsNullOrEmpty(envStr)) update.Add("envStr", envStr);
                accountId = update.Create();
            }

            NotifyCore.Notify(new NifyMessage
            {
                message = $"【京东{accountId}:{company}】cookie 上线",
                tags = ["green_circle"]
            });
            _ = EndPointCore.NotifyReload(true);
            //NotifyCore.QYWeixinPushNotifyAsync("上线", $"【淘宝联盟:{dnk}】cookie 上报更新");
            return accountId;
        }


        public static async Task DisabledAsync(int accountId, string name, string content)
        {
            string cache_key = $"cache:jd_pool:{name}:disabled";
            long count = await RedisKit.IncrByAsync(cache_key);
            _ = RedisKit.ExpireAsync(cache_key, 10);
            if (count > 1) return;

            var update = new DBContext.Table("jd_pool").Add("status", 0);
            if (accountId > 0)
            {
                update.Where("id=@accountId", new { accountId }).Update();
            }
            else
            {
                update.Where("name=@name", new { name }).Update();
            }
            _ = ListAsync(true);
            _ = AllListAsync(true);
            NotifyCore.Notify(new NifyMessage
            {
                message = $"【京东联盟{accountId}:{name}】cookie 掉线\n\n{content}",
                priority = NifyMessagePriority.high,
                tags = ["red_circle"]
            });

            //NotifyCore.QYWeixinPushNotifyAsync("掉线", $"【京东{accountId}:{name}】cookie 掉线");
            _ = EndPointCore.NotifyReload(true);
        }




        internal static async Task AccountExhaustedAsync()
        {
            string cache_key = $"cache:tk_pool:account:exhausted";
            long count = await RedisKit.IncrByAsync(cache_key);
            if (count > 1) return;
            _ = RedisKit.ExpireAsync(cache_key, 3600);
            NotifyCore.Notify(new NifyMessage
            {
                message = $"【京东联盟】{EndPointCore.CurrentEndPoint}没有匹配账号",
                priority = NifyMessagePriority.high,
                tags = ["red_circle"]
            });
            _ = NotifyCore.QYWeixinPushNotifyAsync("没账号", $"【京东联盟】没有匹配账号");
        }
    }


}
