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 Spire.Pdf.Exporting.XPS.Schema;
using System.Xml.Linq;
using System.Net;
using TencentCloud.Mrs.V20200910.Models;
using static molilian.core.TkPoolCore;
using Org.BouncyCastle.Tls;
using MySql.Data.MySqlClient;
using System.Data;


namespace molilian.core
{
    public partial class EndPointCore
    {
        private static readonly object _lockObj = new();
        private static IEnumerable<EndPointDTO> _cached;
        public static IDbConnection GetDbConnection(string connString)
        {
            var conn = new MySqlConnection(connString);
            return conn;
        }

        public static EndPointDTO GetOne(string node)
        {
            var list = List();
            if (!list.Any()) return null;
            var item = list.Where(s => s.name == node).FirstOrDefault();
            return item;
        }


        public static EndPointDTO GetCouponAdmin()
        {
            var list = List();
            if (!list.Any()) return null;
            var item = list.Where(s => s.is_coupon_api && !s.is_public_api).FirstOrDefault();


#if DEBUG
            item.db_server = "Server=rm-2ze74506m3gfsqe7mco.rwlb.rds.aliyuncs.com; Port=3306; Database=coupon; Uid=coupon; Pwd=67ktWBmw5G4yMs4J;SslMode=None;CharSet=utf8mb4;ConnectionTimeout=60;";
#endif
            /*
Server=rm-2zey1jqxnoqy9mcc0zo.rwlb.rds.aliyuncs.com; Port=3306; Database=taoke; Uid=taoke; Pwd=67ktWBmw5G4yMs4J;SslMode=None;CharSet=utf8mb4;ConnectionTimeout=60
Server=rm-2zey1jqxnoqy9mcc0zo.rwlb.rds.aliyuncs.com; Port=3306; Database=taoke; Uid=taoke; Pwd=67ktWBmw5G4yMs4J;SslMode=None;CharSet=utf8mb4;ConnectionTimeout=60
Server=rm-2zey1jqxnoqy9mcc0zo.rwlb.rds.aliyuncs.com; Port=3306; Database=taoke; Uid=taoke; Pwd=67ktWBmw5G4yMs4J;SslMode=None;CharSet=utf8mb4;ConnectionTimeout=60
Server=rm-2ze74506m3gfsqe7mco.rwlb.rds.aliyuncs.com; Port=3306; Database=coupon; Uid=coupon; Pwd=67ktWBmw5G4yMs4J;SslMode=None;CharSet=utf8mb4;ConnectionTimeout=60;
             
             */
            return item;
        }

        public static EndPointDTO GetParseAdmin()
        {
            var list = List();
            if (!list.Any()) return null;
            var item = list.Where(s => !s.is_coupon_api && !s.is_public_api).FirstOrDefault();

#if DEBUG
            item.db_server = "Server=rm-2zey1jqxnoqy9mcc0zo.rwlb.rds.aliyuncs.com; Port=3306; Database=taoke; Uid=taoke; Pwd=67ktWBmw5G4yMs4J;SslMode=None;CharSet=utf8mb4;ConnectionTimeout=60;";
#endif
            return item;
        }

        public static IEnumerable<EndPointDTO> List(bool force = false)
        {
            if (!force && _cached != null) return _cached;

            string cache_key = $"cache:end_point";
            var list = RedisHelper.Get<IEnumerable<EndPointDTO>>(cache_key);
            if (force || list == null)
            {
                lock (_lockObj)
                {
                    list = new DBContext.Table("end_point")
                        .Where("status=@status", new { status = 1 })
                        .Select<EndPointDTO>();
                    if (list == null) return default;
                    RedisHelper.Set(cache_key, list, 30 * 86400);
                }
            }
            _cached = list;
            return list;
        }
        public static void Refresh()
        {
            _ = List(true);
        }

        public static List<T> ProcessEndPointNodes<T>(Func<EndPointDTO, T> nodeAction, bool force = false)
        {
            var resultList = new List<T>();
            var list = List(force);
            foreach (var node in list)
            {
                var result = nodeAction(node);
                if (result != null) resultList.Add(result);
            }
            return resultList;
        }

        public static async Task ProcessEndPointNodesAsync(Func<EndPointDTO, Task> nodeAction, bool force = false)
        {
            var list = List(force);
            var tasks = new List<Task>();
            foreach (var node in list)
            {
                tasks.Add(nodeAction(node));
            }
            await Task.WhenAll(tasks);
        }


        public static async Task NotifyReload(bool onlyAccount = false, CancellationToken cancellationToken = default)
        {
            await ProcessEndPointNodesAsync(async node =>
            {
                try
                {
                    string url = $"{node.api_server}Task_70160bd632/reload";
                    if (onlyAccount) url = $"{node.api_server}Task_70160bd632/reloadAccount";
                    await new WebClientUtility().RequestAsync(url, "GET", cancellationToken);
                }
                catch (Exception ex)
                {
                    _ = new LoggerLibrary("NotifyReload", "error")
                    .Info(node.Convert2Json())
                    .Info(ex.Message, ex.StackTrace)
                    .SaveAsync();

                    NotifyCore.Notify(new NifyMessage
                    {
                        message = $"【NotifyReload异常】{node.description}\n{ex.Message}\n{ex.StackTrace}",
                        priority = NifyMessagePriority.high,
                        tags = ["red_circle"]
                    });
                }
            });
        }



        public static List<(string, string)> NotifyCheckDeepUrl(int accountid, CancellationToken cancellationToken = default)
        {
            var result = ProcessEndPointNodes<(string, string)>(node =>
            {
                try
                {
                    if (!node.is_public_api) return (node.name, "break");
                    if (!node.status) return (node.name, "账号下线");

                    string url = $"{node.api_server}Task_70160bd632/CheckDeepUrl?accountid={accountid}";
                    var result = new WebClientUtility().Request(url, "GET");
                    string body = result.Body();
                    var root = body.Convert2JsonElement();
                    var message = root.Read<string>("message", string.Empty);
                    return (node.name, message);
                    

                }
                catch (Exception ex)
                {
                    _ = new LoggerLibrary("CheckDeepUrl", "error")
                    .Info(node.Convert2Json(), $"accountid:\t{accountid}")
                    .Info(ex.Message, ex.StackTrace)
                    .SaveAsync();

                    NotifyCore.Notify(new NifyMessage
                    {
                        message = $"【CheckDeepUrl异常】{node.description}\n{ex.Message}\n{ex.StackTrace}",
                        priority = NifyMessagePriority.high,
                        tags = ["red_circle"]
                    });
                    return (node.name, ex.Message);
                }
            });
            return result;
        }

    }

}
