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;

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>();

                }


            })
                    .AddDataAnnotationsLocalization(options =>
                    {
                        options.DataAnnotationLocalizerProvider = (type, factory) =>
                            factory.Create(typeof(SharedResource));
                    })
                .AddNewtonsoftJsonSetup(); // NewtonsoftJson ���л�  ����


            //services.AddScoped<IAuditingData, AuditingData>();

            //��̬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>();

        }

        // 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();

            //����Ҫ token ���ʵľ�̬�ļ�  wwwroot css, JavaScript, and images don't require authentication.
            app.UseStaticFiles();

            app.UseIRacisHostStaticFileStore(env);

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

            //hangfire
            app.UseHangfireConfig(env);

            // //��ʱ����
            //app.UseHttpReports();

            //���� ��
            //app.UseIpRateLimiting();

            //��Ӧѹ��
            app.UseResponseCompression();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                //app.UseHsts();
            }
            Console.WriteLine("��ǰ������ " + env.EnvironmentName);

            //app.UseMiddleware<AuthMiddleware>();

            // �����쳣���� ���� 404 
            app.UseStatusCodePagesWithReExecute("/Error/{0}");

            SwaggerSetup.Configure(app, env);



            //serilog ��¼������û���Ϣ
            app.UseSerilogConfig(env);

            app.UseRouting();

            app.UseAuthentication();
            //app.UseJwtBearerQueryString();
            app.UseAuthorization();

            //�ļ��ŷ�  �����Token ����
            //app.UseIRacisHostStaticFileStore(env);

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

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapHub<UploadHub>("/UploadHub" )/*.RequireCors(t=>t.WithOrigins(new string[] {"null"}).AllowAnyMethod().AllowAnyHeader().AllowCredentials())*/;

                endpoints.MapControllers();
            });

        }
    }
}