using AgileConfig.Client;

using CloudGaming.Code.DataAccess;
using CloudGaming.Code.DataAccess.MultiTenantUtil;
using CloudGaming.Code.Game;

using HuanMeng.DotNetCore.CacheHelper;
using HuanMeng.DotNetCore.Redis;

using Refit;

using StackExchange.Redis;

using System.Collections.Concurrent;
using System.Collections.Frozen;
using System.Net.Http.Json;


namespace CloudGaming.Code.AppExtend
{
    /// <summary>
    /// app配置项扩展
    /// </summary>
    public static class AppConfigurationExtend
    {
        /// <summary>
        /// 配置数据
        /// </summary>
        //public static ConfigClient AppConfigClient { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public static IConfigurationManager ConfigurationManager { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public static ConcurrentDictionary<string, AppConfig> AppConfigs { get; set; } = new ConcurrentDictionary<string, AppConfig>();

        /// <summary>
        /// 多语言配置
        /// </summary>
        public static ConcurrentDictionary<string, List<string>> AppConfigLanguages { get; set; } = new ConcurrentDictionary<string, List<string>>();

        /// <summary>
        /// 获取配置项
        /// </summary>
        /// <param name="domainName"></param>
        /// <returns></returns>
        public static AppConfig GetAppConfig(string domainName)
        {
            if (AppConfigs.TryGetValue(domainName, out var appConfig))
            {
                return appConfig;
            }
            if (AppConfigs.TryGetValue("default", out appConfig))
            {
                return appConfig;
            }

            return AppConfigs.FirstOrDefault().Value;
        }
        /// <summary>
        /// 获取配置项
        /// </summary>
        /// <param name="domainName"></param>
        /// <returns></returns>
        public static AppConfig GetAppConfig(Guid tenantId)
        {
            var appConfig = AppConfigs.Where(it => it.Value.TenantId == tenantId).Select(it => it.Value).FirstOrDefault();
            if (appConfig != null)
            {
                return appConfig;
            }
            if (AppConfigs.TryGetValue("default", out appConfig))
            {
                return appConfig;
            }

            return AppConfigs.FirstOrDefault().Value;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="args"></param>
        public static void ConfigClient_ConfigChanged(ConfigReloadedArgs args)
        {

            if (args.OldConfigs.TryGetValue("Version", out var vresion) && args.NewConfigs.TryGetValue("Version", out var newVersion))
            {
                if (vresion != newVersion)
                {
                    MemoryCacheHelper.cache.Clear();
                }
            }
            VerifyTenant(args);
            //if (VerifyTenant(args, "Payment:WeChatConfig"))
            //{
            //    PaymentExtend.AddWeChat(ConfigurationManager);
            //}
            //if (VerifyTenant(args, "Payment:AlipayConfig"))
            //{
            //    PaymentExtend.AddAlipay(ConfigurationManager);

            //}
        }


        /// <summary>
        /// 初始化app
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static async Task<IHostApplicationBuilder> AddAppConfigClient(this WebApplicationBuilder builder)
        {

            var configClient = new ConfigClient(builder.Configuration);
            builder.Host.UseAgileConfig(configClient, ConfigClient_ConfigChanged);
            ConfigurationManager = builder.Configuration;
            await AppConfigInit(builder.Configuration);
            builder.Services.AddScoped<AppConfig>();
            builder.AddDataBase();
            builder.AddAppService();
            return builder;

        }
        /// <summary>
        /// 初始化app服务
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public static IHostApplicationBuilder AddAppService(this WebApplicationBuilder builder)
        {
            builder.Services.AddHostedService<AppService>();
            return builder;
        }

        /// <summary>
        /// 获取配置项
        /// </summary>
        /// <param name="identifier"></param>
        /// <returns></returns>
        public static AppConfig? GetAppConfigIdentifier(string identifier)
        {
            var app = AppConfigs.Where(it => it.Value.Identifier == identifier).Select(it => it.Value).FirstOrDefault();

            return app;
        }


        /// <summary>
        /// 配置版本号
        /// </summary>
        public static string AppVersion
        {
            get;
            set;
        }



        #region 租户
        /// <summary>
        /// 
        /// </summary>
        /// <param name="appConfig"></param>
        /// <param name="tenantInfo"></param>
        /// <returns></returns>
        public static ITenantInfo ToITenantInfo(this AppConfig appConfig, ITenantInfo? tenantInfo = null)
        {
            if (tenantInfo == null)
            {
                tenantInfo = new TenantInfo();
            }
            tenantInfo.TenantId = appConfig.TenantId;
            tenantInfo.Identifier = appConfig.Identifier;
            tenantInfo.Name = appConfig.Name;
            return tenantInfo;
        }
        /// <summary>
        /// 获取redis缓存
        /// </summary>
        /// <param name="appConfig"></param>
        /// <returns></returns>
        public static IDatabase GetRedisDataBase(this AppConfig appConfig)
        {
            return RedisConnection.GetRedis(appConfig.RedisConnectionString);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="redisConnection"></param>
        /// <returns></returns>
        public static IServer GetRedisServer(this AppConfig appConfig)
        {
            return RedisConnection.GetServer(appConfig.RedisConnectionString);
        }

        /// <summary>
        /// 获取Dao
        /// </summary>
        /// <param name="appConfig"></param>
        /// <returns></returns>
        public static DAO GetDAO(this IServiceProvider serviceProvider, AppConfig appConfig)
        {
            return new DAO(serviceProvider, appConfig);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="appConfig"></param>
        /// <param name="newAppConfig"></param>
        /// <returns></returns>
        public static AppConfig ToAppConfig(this AppConfig appConfig, AppConfig? newAppConfig = null)
        {
            if (newAppConfig == null)
            {
                newAppConfig = new AppConfig();
            }
            if (appConfig == null)
            {
                appConfig = new AppConfig();
            }
            newAppConfig.TenantId = appConfig.TenantId;
            newAppConfig.Identifier = appConfig.Identifier;
            newAppConfig.Name = appConfig.Name;
            newAppConfig.DomainName = appConfig.DomainName;
            newAppConfig.RedisConnectionString = appConfig.RedisConnectionString;
            newAppConfig.UserConnectionString = appConfig.UserConnectionString;
            newAppConfig.GameConnectionString = appConfig.GameConnectionString;
            newAppConfig.ExtConnectionString = appConfig.ExtConnectionString;
            newAppConfig.PhoneConnectionString = appConfig.PhoneConnectionString;
            newAppConfig.AliyunConfig = appConfig.AliyunConfig;
            newAppConfig.DefaultLanguage = appConfig.DefaultLanguage ?? "zh";
            if (appConfig.UserConfig == null)
            {
                appConfig.UserConfig = new UserConfig();
            }
            newAppConfig.UserConfig = appConfig.UserConfig;
            newAppConfig.Payment = appConfig.Payment;
            newAppConfig.GameConfig = appConfig.GameConfig;
            newAppConfig.PrivacyAgreement = appConfig.PrivacyAgreement;
            newAppConfig.UserAgreement = appConfig.UserAgreement;
            newAppConfig.LanguageRequestUrl = appConfig.LanguageRequestUrl;
            newAppConfig.CacheRequestUrls = appConfig.CacheRequestUrls;
            return newAppConfig;
        }

        /// <summary>
        /// 验证多租户
        /// </summary>
        /// <param name="args"></param>
        private static bool VerifyTenant(ConfigReloadedArgs args, string key)
        {
            var newTenant = args.NewConfigs.Where(it => it.Key.Contains(key)).ToDictionary();
            var oldTenant = args.OldConfigs.Where(it => it.Key.Contains(key)).ToDictionary();
            bool areEqual = newTenant.Count == oldTenant.Count &&
                !newTenant.Except(oldTenant).Any();
            if (!areEqual)
            {
                //更新缓存
                //AppConfigInit(ConfigurationManager);
                return true;
            }
            return false;
        }
        /// <summary>
        /// 验证多租户
        /// </summary>
        /// <param name="args"></param>
        private static void VerifyTenant(ConfigReloadedArgs args)
        {
            var newTenant = args.NewConfigs.Where(it => it.Key.Contains("Tenants")).ToDictionary();
            var oldTenant = args.OldConfigs.Where(it => it.Key.Contains("Tenants")).ToDictionary();
            bool areEqual = newTenant.Count == oldTenant.Count &&
                !newTenant.Except(oldTenant).Any();
            if (!areEqual)
            {
                //更新缓存
                AppConfigInit(ConfigurationManager);
            }

        }

        /// <summary>
        /// 初始化租户数据
        /// </summary>
        /// <param name="configurationManager"></param>
        private static async Task AppConfigInit(IConfigurationManager configurationManager)
        {
            var tenants = configurationManager.GetSection("Tenants").Get<List<AppConfig>>();
            if (tenants != null)
            {
                ConcurrentDictionary<string, AppConfig> _AppConfigs = new ConcurrentDictionary<string, AppConfig>();
                if (tenants.Count > 0)
                {
                    foreach (var t in tenants)
                    {
                        if (!_AppConfigs.TryAdd(t.DomainName, t))
                        {
                            Console.WriteLine($"{t.DomainName}配置加载失败");
                        }
                        var list = await GetAppConfigLanguage(t.LanguageRequestUrl);
                        AppConfigLanguages.TryAdd(t.DomainName, list);
                        if (t.Name == "default")
                        {
                            _AppConfigs.TryAdd("default", t);
                        }
                    }

                    if (!_AppConfigs.TryGetValue("default", out var x))
                    {
                        _AppConfigs.TryAdd("default", tenants[0]);
                    }
                }
                else
                {
                    _AppConfigs.TryAdd("default", new AppConfig());
                }
                AppConfigs = _AppConfigs;
            }
        }

        /// <summary>
        /// 获取项目的多语言
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private static async Task<List<string>> GetAppConfigLanguage(string url)
        {
            if (string.IsNullOrEmpty(url))
            {
                return new List<string>() { "zh" };
            }
            using HttpClient _httpClient = new HttpClient();
            try
            {
                // 发送GET请求到指定的URL
                var response = await _httpClient.GetFromJsonAsync<BaseResponse<List<Dictionary<string, object>>>>(url);

                // 检查响应是否为null，以及响应码是否为200
                if (response != null && response.Code == 200)
                {
                    if (response.Data != null && response.Data.Count > 0)
                    {
                        var list = response.Data.Select(it => it["value"].ToString() ?? "").ToList();
                        return list;

                    }
                }
            }
            catch (Exception ex)
            {

            }
            return new List<string>() { "zh" };
        }
        #endregion

        /// <summary>
        /// 获取多语言
        /// </summary>
        /// <param name="appConfig"></param>
        /// <returns></returns>
        public static List<string> GetLanguages(this AppConfig appConfig)
        {
            if (appConfig != null)
            {
                if (AppConfigLanguages.TryGetValue(appConfig.DomainName, out var list))
                {
                    return list;
                }
            }
            return new List<string>() { "zh" };
        }
    }

}
