using COMMON;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Models;
using Models.Models.DEBUGGER_DB;
using Models.Models.Engineering;
using Models.Models.LOGDB;
using Quartz;
using Quartz.Impl;
using System.IO;
using System.IO.Compression;
using System.Linq;
using WebUI.LIB;
using static System.Net.Mime.MediaTypeNames;

namespace WebUI
{
    /// <summary>
    /// 启动配置
    /// </summary>
    public class Startup
    {
          
        /// <summary>
        ///  sql 输出
        /// </summary>
        // 添加静态ILoggerFactory 用于显示ef执行的sql
        public static readonly ILoggerFactory efLogger = LoggerFactory.Create(builder =>
        {
            builder.AddFilter((category, level) => category == DbLoggerCategory.Database.Command.Name && level == LogLevel.Information).AddConsole();
        });

        /// <summary>
        /// 有参构造
        /// </summary>
        /// <param name="configuration"></param>
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration; 
        }
        /// <summary>
        /// 配置容器
        /// </summary>
        public IConfiguration Configuration { get; }
        /// <summary>
        /// 依赖注入
        /// </summary>
        /// <param name="services"></param>
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //配置文件绑定
            Configuration.GetSection("ConfigEntity").Bind(ConfigEntity.Instance);
            Configuration.GetSection("JwtConst").Bind(JwtConst.Instance);
            services.AddResponseCompression();

            services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

            services.AddDbContext<DEBUGGER_DB>(opt =>
                                           opt.UseSqlServer(ConfigEntity.Instance.DEBUGGER_DB,
                                               b => b.MigrationsAssembly("WebUI")).UseLoggerFactory(efLogger));
            if (ConfigEntity.Instance.DBTYPE == 1)
            {
                services.AddDbContext<HotelServiceContext>(opt =>
                                           opt.UseSqlServer(ConfigEntity.Instance.Connection,
                                           b => b.MigrationsAssembly("WebUI")).UseLoggerFactory(efLogger));
                services.AddDbContext<LOG_DBContext>(opt =>
                                               opt.UseSqlServer(ConfigEntity.Instance.Connection_log,
                                               // 添加静态ILoggerFactory 用于显示ef执行的sql
                                               b => b.MigrationsAssembly("WebUI")).UseLoggerFactory(efLogger));

                services.AddDbContext<Engineering_Management>(opt =>
                                        opt.UseSqlServer(ConfigEntity.Instance.Engineering_DB,
                                        b => b.MigrationsAssembly("WebUI")).UseLoggerFactory(efLogger));
            }
            if (ConfigEntity.Instance.DBTYPE == 2)
            {
                services.AddDbContext<HotelServiceContext>(opt =>
                                           opt.UseMySQL(ConfigEntity.Instance.Connection,
                                           b => b.MigrationsAssembly("WebUI")).UseLoggerFactory(efLogger));
                services.AddDbContext<LOG_DBContext>(opt =>
                                               opt.UseMySQL(ConfigEntity.Instance.Connection_log,
                                               // 添加静态ILoggerFactory 用于显示ef执行的sql
                                               b => b.MigrationsAssembly("WebUI")).UseLoggerFactory(efLogger));
                services.AddDbContext<Engineering_Management>(opt =>
                                       opt.UseMySQL(ConfigEntity.Instance.Engineering_DB,
                                       b => b.MigrationsAssembly("WebUI")).UseLoggerFactory(efLogger));
            }
            // 比 newjson 
            services.AddControllersWithViews().AddJsonOptions(opt =>
                {
                    //原样输出,默认会把首字母小写
                    opt.JsonSerializerOptions.PropertyNamingPolicy = null;
                    // 格式化时间类型
                    opt.JsonSerializerOptions.Converters.Add(new DateTimeStr());
                }).AddRazorRuntimeCompilation();

            services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();

            services.AddResponseCompression(options =>
            {
                options.Providers.Add<BrotliCompressionProvider>();
                options.Providers.Add<GzipCompressionProvider>();

                options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(new[] { "image/svg+xml" });
            });

            //配置BrotliCompression 压缩级别  Optimal(最佳的压缩方式,耗费的时间较长)  Fastest(最快的压缩方式) NoCompression(不进行压缩)
            services.Configure<BrotliCompressionProviderOptions>(config =>
            {
                config.Level = CompressionLevel.Fastest;
            });

            //配置Gzip  压缩级别  Optimal(最佳的压缩方式,耗费的时间较长)  Fastest(最快的压缩方式) NoCompression(不进行压缩)
            services.Configure<GzipCompressionProviderOptions>(config =>
            {
                config.Level = CompressionLevel.Fastest;
            });

        }


        /// <summary>
        /// 中间件处理
        /// </summary>
        /// <param name="app"></param>
        /// <param name="env"></param>
        /// <param name="applicationLeftTime"></param>
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime applicationLeftTime)
        {
          

            //添加jwt验证
            app.UseAuthentication();

            if (env.IsDevelopment())
            {
                var developerExceptionPageOptions = new DeveloperExceptionPageOptions();
                // 显示代码行数
                developerExceptionPageOptions.SourceCodeLineCount = 10;
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // 错误页
                app.UseExceptionHandler(exceptionHandlerApp =>
                {
                    exceptionHandlerApp.Run(async context =>
                    {
                        context.Response.StatusCode = StatusCodes.Status500InternalServerError;

                        context.Response.ContentType = Text.Plain;

                        await context.Response.WriteAsync("An exception was thrown.");

                        var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();

                        if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
                        {
                            await context.Response.WriteAsync(" The file was not found.");
                        }

                        if (exceptionHandlerPathFeature?.Path == "/")
                        {
                            await context.Response.WriteAsync(" Page: Home.");
                        }
                    });
                });
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                //app.UseHsts();
            }
            //app.UseHttpsRedirection();

            // 放在 UseStaticFiles 之前  添加防盗链中间件 
            //  app.UseMiddleware<BadLink>();

            
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });

            //必须在任何压缩响应的中间件之前调用 
            app.UseResponseCompression();

            applicationLeftTime.ApplicationStopped.Register(() => {
                LogHelp.Error("ApplicationStopped...");
                TcpServer.Tcp.Close();
            });
        }
    }
}
