using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Builder;
using Consul;
using Siger.Middlelayer.Common.AppSettings;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Log;
using Microsoft.Extensions.Hosting;
namespace Siger.ApiCommon.Utilities
{
    public static class Consul
    {
        /// <summary>
        /// 注册 Consul
        /// </summary>
        /// <param name="app"></param>
        /// <param name="module"></param>
        /// <param name="lifetime"></param>
        /// <returns></returns>
        public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, Module module, IHostApplicationLifetime lifetime)
        {
            var enabledSetting = Config<ConsulEnableSetting>.Get();
            if (enabledSetting == null || enabledSetting.ConsulEnabledSetting.Enabled != 1)
            {
                return app;
            }
            var serviceEntity = GetEntity(module);
            if (serviceEntity != null)
            {
                var consulClient = new ConsulClient(x => x.Address = new Uri($"http://{serviceEntity.ConsulIP}:{serviceEntity.ConsulPort}"));//请求注册的 Consul 地址
                var httpCheck = new AgentServiceCheck()
                {
                    DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册
                    Interval = TimeSpan.FromSeconds(30),//健康检查时间间隔，或者称为心跳间隔
                    HTTP = $"http://{serviceEntity.IP}:{serviceEntity.Port}{serviceEntity.HealthUrl}",//健康检查地址
                    Timeout = TimeSpan.FromSeconds(3)
                };

                // RegisterConsul service with consul
                var registration = new AgentServiceRegistration()
                {
                    Checks = new[] { httpCheck },
                    ID = Guid.NewGuid().ToString(),
                    Name = serviceEntity.ServiceName,
                    Address = serviceEntity.IP,
                    Port = serviceEntity.Port,
                    Tags = new[] { $"urlprefix-/{serviceEntity.ServiceName}" }//添加 urlprefix-/servicename 格式的 tag 标签，以便 Fabio 识别
                };

                //consulClient.Agent.ServiceRegister(registration).Wait();//服务启动时注册，内部实现其实就是使用 Consul API 进行注册（HttpClient发起）
                //lifetime.ApplicationStopping.Register(() =>
                //{
                //    consulClient.Agent.ServiceDeregister(registration.ID).Wait();//服务停止时取消注册
                //});

            }
            return app;
        }
        /// <summary>
        /// 读取配置
        /// </summary>
        /// <param name="module"></param>
        /// <returns></returns>
        static ServiceEntity GetEntity(Module module)
        {
            try
            {
               var consulSetting = Config<ApiConsulSetting>.GetConsul();
                if (consulSetting == null)
                {
                    return null;
                }
                switch (module)
                {
                    case Module.Acc:
                        {
                            var apiAccSetting = Config<ApiACCSetting>.GetConsul();
                            return new ServiceEntity
                            {
                                IP = apiAccSetting.ACCSetting.ServiceIP,
                                Port = apiAccSetting.ACCSetting.ServicePort,
                                ServiceName = apiAccSetting.ACCSetting.ServiceName,
                                ConsulIP = consulSetting.ConsulSetting.ConsulIP,
                                ConsulPort = consulSetting.ConsulSetting.ConsulPort
                            };
                        }                       
                    case Module.Cnc:
                        {
                            var apiCncSetting = Config<ApiCNCSetting>.GetConsul();
                            return new ServiceEntity
                            {
                                IP = apiCncSetting.CNCSetting.ServiceIP,
                                Port = apiCncSetting.CNCSetting.ServicePort,
                                ServiceName = apiCncSetting.CNCSetting.ServiceName,
                                ConsulIP = consulSetting.ConsulSetting.ConsulIP,
                                ConsulPort = consulSetting.ConsulSetting.ConsulPort
                            };
                        }
                    case Module.Dnc:
                        {
                            var apiDncSetting = Config<ApiDNCSetting>.GetConsul();
                            return new ServiceEntity
                            {
                                IP = apiDncSetting.DNCSetting.ServiceIP,
                                Port = apiDncSetting.DNCSetting.ServicePort,
                                ServiceName = apiDncSetting.DNCSetting.ServiceName,
                                ConsulIP = consulSetting.ConsulSetting.ConsulIP,
                                ConsulPort = consulSetting.ConsulSetting.ConsulPort
                            };
                        }
                    case Module.Tools:
                        {
                            var apiToolsSetting = Config<ApiToolsSetting>.GetConsul();
                            return new ServiceEntity
                            {
                                IP = apiToolsSetting.ToolsSetting.ServiceIP,
                                Port = apiToolsSetting.ToolsSetting.ServicePort,
                                ServiceName = apiToolsSetting.ToolsSetting.ServiceName,
                                ConsulIP = consulSetting.ConsulSetting.ConsulIP,
                                ConsulPort = consulSetting.ConsulSetting.ConsulPort
                            };

                        }
                    case Module.Config:
                        {
                            var apiConfigSetting = Config<ApiConfigSetting>.GetConsul();
                            return new ServiceEntity
                            {
                                IP = apiConfigSetting.ConfigSetting.ServiceIP,
                                Port = apiConfigSetting.ConfigSetting.ServicePort,
                                ServiceName = apiConfigSetting.ConfigSetting.ServiceName,
                                ConsulIP = consulSetting.ConsulSetting.ConsulIP,
                                ConsulPort = consulSetting.ConsulSetting.ConsulPort
                            };
                          
                        }
                    case Module.Wms:
                        {
                            var apiWmsSetting = Config<ApiWmsSetting>.GetConsul();
                            return new ServiceEntity
                            {
                                IP = apiWmsSetting.WmsSetting.ServiceIP,
                                Port = apiWmsSetting.WmsSetting.ServicePort,
                                ServiceName = apiWmsSetting.WmsSetting.ServiceName,
                                ConsulIP = consulSetting.ConsulSetting.ConsulIP,
                                ConsulPort = consulSetting.ConsulSetting.ConsulPort
                            };
                        }
                    case Module.Tpm:
                    {
                        var apiTpmSetting = Config<ApiTpmSetting>.GetConsul();
                        return new ServiceEntity
                        {
                            IP = apiTpmSetting.TpmSetting.ServiceIP,
                            Port = apiTpmSetting.TpmSetting.ServicePort,
                            ServiceName = apiTpmSetting.TpmSetting.ServiceName,
                            ConsulIP = consulSetting.ConsulSetting.ConsulIP,
                            ConsulPort = consulSetting.ConsulSetting.ConsulPort
                        };
                    }
                    case Module.Tlm:
                    {
                        var apiTpmSetting = Config<ApiTlmSetting>.GetConsul();
                        return new ServiceEntity
                        {
                            IP = apiTpmSetting.TlmSetting.ServiceIP,
                            Port = apiTpmSetting.TlmSetting.ServicePort,
                            ServiceName = apiTpmSetting.TlmSetting.ServiceName,
                            ConsulIP = consulSetting.ConsulSetting.ConsulIP,
                            ConsulPort = consulSetting.ConsulSetting.ConsulPort
                        };
                    }
                    case Module.Dashboard:
                    {
                        var apiTpmSetting = Config<ApiDashboardSetting>.GetConsul();
                        return new ServiceEntity
                        {
                            IP = apiTpmSetting.DashboardSetting.ServiceIP,
                            Port = apiTpmSetting.DashboardSetting.ServicePort,
                            ServiceName = apiTpmSetting.DashboardSetting.ServiceName,
                            ConsulIP = consulSetting.ConsulSetting.ConsulIP,
                            ConsulPort = consulSetting.ConsulSetting.ConsulPort
                        };
                    }
                    default:
                        {
                            return null;
                        }
                }
            }
            catch (Exception e)
            {
                 Task.Run(() => Logger.WriteLineErrorAsync(e.ToString()));
            }
            return null;
        }
    }
}
