using Autofac;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using IRaCIS.Core.Application.Filter;
using LogDashboard;
using MediatR;
using IRaCIS.Core.Application.MediatR.Handlers;
using Microsoft.Extensions.Logging;
using AspNetCoreRateLimit;
using Microsoft.AspNetCore.HttpOverrides;
using IRaCIS.Core.Infra.EFCore;
using System.Globalization;
using Microsoft.AspNetCore.Localization;
using Localization;
using Magicodes.ExporterAndImporter.Core.Filters;
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
using IRaCIS.Core.Infra.EFCore.Common;
using Invio.Extensions.Authentication.JwtBearer;
using Microsoft.AspNetCore.SignalR;
using IRaCIS.Core.Domain.Share;

namespace IRaCIS.Core.API
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            _configuration = configuration;
        }
        public ILogger<Startup> _logger { get; }

        public IConfiguration _configuration { get; }

        //// ConfigureContainer is where you can register things directly
        //// with Autofac. This runs after ConfigureServices so the things
        //// here will override registrations made in ConfigureServices.
        //// Don't build the container; that gets done for you by the factory.
        // for castle
        public void ConfigureContainer(ContainerBuilder containerBuilder)
        {
            containerBuilder.RegisterModule<AutofacModuleSetup>();

            #region  Test
            //containerBuilder.RegisterType<ClinicalDataService>().PropertiesAutowired().InstancePerLifetimeScope();//注册仓储

            //var container = containerBuilder.Build();

            //// Now you can resolve services using Autofac. For example,
            //// this line will execute the lambda expression registered
            //// to the IConfigReader service.
            //using (var scope = container.BeginLifetimeScope())
            //{
            //    var reader = scope.Resolve<BaseService>();

            //    var test = scope.Resolve<ClinicalDataService>();
            //    var test2 = scope.Resolve<IClinicalDataService>();

            //    var test3 = scope.Resolve<IEFUnitOfWork<IRaCISDBContext>>();
            //}
            #endregion
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //本地化
            services.AddJsonLocalization(options => options.ResourcesPath = "Resources");

            // 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
            services.AddControllers(options =>
            {
                //options.Filters.Add<LogActionFilter>();
                options.Filters.Add<ModelActionFilter>();
                options.Filters.Add<ProjectExceptionFilter>();
                options.Filters.Add<UnitOfWorkFilter>();

                if (_configuration.GetSection("BasicSystemConfig").GetValue<bool>("OpenLoginLimit"))
                {
                    options.Filters.Add<LimitUserRequestAuthorization>();

                }


            })

                .AddNewtonsoftJsonSetup(); // NewtonsoftJson 序列化  处理

            services.AddOptions().Configure<SystemEmailSendConfig>( _configuration.GetSection("SystemEmailSendConfig"));
            services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));



            //动态WebApi + UnifiedApiResultFilter  省掉控制器代码
            services.AddDynamicWebApiSetup();
            //AutoMapper
            services.AddAutoMapperSetup();
            //EF ORM  QueryWithNoLock
            services.AddEFSetup(_configuration);
            //Http 响应压缩
            services.AddResponseCompressionSetup();
            //Swagger Api 文档
            services.AddSwaggerSetup();
            //JWT Token 验证
            services.AddJWTAuthSetup(_configuration);
            // MediatR 进程内消息 事件解耦  从程序集中 注册命令和handler对应关系
            services.AddMediatR(typeof(ConsistencyVerificationHandler).Assembly);
            // EasyCaching 缓存
            services.AddEasyCachingSetup();

            //services.AddDistributedMemoryCache();

            // hangfire  定时任务框架  有界面，更友好~
            //services.AddhangfireSetup(_configuration);

            //  QuartZ 定时任务框架  使用了hangfire 暂时不用，后续需要可以打开，已经配好
            services.AddQuartZSetup(_configuration);

            // 保护上传文件
            //services.AddStaticFileAuthorizationSetup();


            ////HttpReports 暂时废弃
            //services.AddHttpReports().AddHttpTransport();
            //Serilog 日志可视化 LogDashboard日志
            services.AddLogDashboardSetup();
            //上传限制 配置
            services.Configure<FormOptions>(options =>
            {
                options.MultipartBodyLengthLimit = int.MaxValue;
                options.ValueCountLimit = int.MaxValue;
                options.ValueLengthLimit = int.MaxValue;
            });
            //IP 限流 可设置白名单 或者黑名单
            //services.AddIpPolicyRateLimitSetup(_configuration);
            // 用户类型 策略授权
            //services.AddAuthorizationPolicySetup(_configuration);

            services.AddJsonConfigSetup(_configuration);
            //转发头设置  获取真实IP 
            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders =
                    ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
            });
            //Dicom影像渲染图片  跨平台
            services.AddDicomSetup();

            // 实时应用
            services.AddSignalR();


            services.AddSingleton<IUserIdProvider, IRaCISUserIdProvider>();

            //services.AddSingleton<IImportResultFilter, ImportResultFilteTest>();

            services.AddMemoryCache();

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            //本地化
            app.UseLocalization();

            app.UseForwardedHeaders();

            //响应压缩
            app.UseResponseCompression();


            //不需要 token 访问的静态文件  wwwroot css, JavaScript, and images don't require authentication.
            app.UseStaticFiles();


            //LogDashboard
            app.UseLogDashboard("/LogDashboard");

            ////hangfire
            //app.UseHangfireConfig(env);




            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                //app.UseHsts();
            }
            Console.WriteLine("当前环境： " + env.EnvironmentName);


            // 特殊异常处理 比如 404 
            app.UseStatusCodePagesWithReExecute("/Error/{0}");

            SwaggerSetup.Configure(app, env);



            ////serilog 记录请求的用户信息
            app.UseSerilogConfig(env);

            app.UseRouting();

            app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

            app.UseIRacisHostStaticFileStore(env);

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {


                endpoints.MapControllers();

                endpoints.MapHub<UploadHub>("/UploadHub");
            });

        }
    }
}
