using EasyMemoryCache;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using Quartz;
using Quartz.Impl;
using Sugar.Enties;
using System;
using System.IO;
using System.Reflection;
using WebAPIBase.Model;
using WebAPIBase.Utils;
using WebAPIBase.Utils.Jwt;

namespace WebAPIBase.API
{
    public class Startup
    {
        private IWebHostEnvironment _env;
        private const string CONTENTROOTPATHTOKEN = "%CONTENTROOTPATH%";
        public Startup(IConfiguration configuration, IWebHostEnvironment env)
        {
            Configuration = configuration;
            _env = env;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            var signingConfigurations = new SigningConfigurations();
            services.AddSingleton(signingConfigurations);
            services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();

            //var tokenConfigurations = new TokenConfigurations();
            //new ConfigureFromConfigurationOptions<TokenConfigurations>(
            //    Configuration.GetSection("TokenConfigurations"))
            //        .Configure(tokenConfigurations);
            //services.AddSingleton(tokenConfigurations);

            Console.WriteLine($"ip:{RequestHelper.GetServerIp()}");
            //设置pdf文件存放路径
            if (RequestHelper.IsRemote)
            {
                services.AddSingleton<IFileProvider>(new PhysicalFileProvider(AppSettingsHelper.Configuration["ServiceVirtualPath:RealPath"]));
            }
            else
            {
                services.AddSingleton<IFileProvider>(new PhysicalFileProvider(AppSettingsHelper.Configuration["LocalVirtualPath:RealPath"]));
            }

            // TODO create options classes for app settings
            var identityConn = AppSettingsHelper.Configuration["Logging:AppSettings:ConnectionString"];

            identityConn = identityConn.Replace(CONTENTROOTPATHTOKEN, _env.ContentRootPath);

            services.AddDbContext<IdentityAuthDbContext>(options => options.UseSqlServer(identityConn));
            services.AddDefaultIdentity<AppUser>().AddEntityFrameworkStores<IdentityAuthDbContext>();

            services.AddMemoryCache();

            #region jwt配置
            services.AddTransient<ITokenHelper, TokenHelper>();
            //读取配置文件配置的jwt相关配置
            services.Configure<JWTConfig>(Configuration.GetSection("JWTConfig"));
            //启用JWT
            services.AddAuthentication(Options =>
            {
                Options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                Options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).
            AddJwtBearer();
            services.AddScoped<Filter.TokenAuthorize>();
            #endregion


            services.AddLogging(log =>
            {
                log.AddConsole();
                log.AddDebug();
            });
            services.AddAuthorization(auth =>
            {
                auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
                    .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
                    .RequireAuthenticatedUser().Build());
            });

            services.AddMvcCore()
                .AddApiExplorer();
            services.AddHttpClient();
            services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
            {
                builder.AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader();
            }));



            services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

            services.AddSingleton<IConfiguration>(Configuration);
            services.AddSingleton<ICaching, Caching>();

            //services.AddAuthorization(options =>
            //{
            //    options.AddPolicy("Member",
            //        policy => policy.RequireClaim("MembershipId"));
            //});

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo { Title = "WebAPIBase API——Netcore 3.1", Version = "v1" });
                c.AddSecurityDefinition("Bearer",
                    new OpenApiSecurityScheme
                    {
                        In = ParameterLocation.Header,
                        Description = "请输入OAuth接口返回的Token，前置Bearer。",
                        Name = "X-Token",
                        Type = SecuritySchemeType.ApiKey
                    });
                c.AddSecurityRequirement(new OpenApiSecurityRequirement {

                    { new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference()
                            {
                            Id = "Bearer",
                            Type = ReferenceType.SecurityScheme
                            }
                        }, Array.Empty<string>()
                    }
                });
                // 为 Swagger 设置xml文档注释路径
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                // 添加控制器层注释，true表示显示控制器注释
                c.IncludeXmlComments(xmlPath, true);

            });

            //services.AddOpenApiDocument(); // registers a OpenAPI v3.0 document with the name "v1" (default)
            //services.AddSwaggerDocument(configure)
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            var isIIS = Convert.ToBoolean(AppSettingsHelper.Configuration["isIIS"]);
            var virtualPath = AppSettingsHelper.Configuration["virtualPath"];
            var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            #region pdf存放路径设置
            if (RequestHelper.IsRemote)
            {
                app.UseStaticFiles(new StaticFileOptions()
                {
                    FileProvider = new PhysicalFileProvider(AppSettingsHelper.Configuration["ServiceVirtualPath:RealPath"]),
                    RequestPath = "/WorkFlowPdf"
                });
            }
            else
            {
                app.UseStaticFiles(new StaticFileOptions()
                {
                    FileProvider = new PhysicalFileProvider(AppSettingsHelper.Configuration["LocalVirtualPath:RealPath"]),
                    RequestPath = "/WorkFlowPdf"
                });
            }
            #endregion

            app.UseHttpsRedirection();

            app.UseRouting();
            //启用认证中间件 要写在授权UseAuthorization()的前面
            app.UseAuthentication();
            app.UseAuthorization();

            ///异常捕获的实现
            app.UseCustomErrorMiddleware();

            app.UseCors();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
            if (isIIS == false)     //若不是IIS部署
            {
                logger.Info($"isIIS:{isIIS}");
                app.UseSwagger();

                app.UseSwaggerUI(c =>
                {
                    c.SwaggerEndpoint("/swagger/v1/swagger.json", "ForSignAPIClient v1");
                });
            }
            else   //若是IIS部署，并且是虚拟目录部署
            {
                logger.Info($"isIIS:{isIIS}");
                //var documentName = "v1";
                app.UseSwagger();
                app.UseSwaggerUI(c =>
                {
                    c.SwaggerEndpoint($"{virtualPath}/swagger/v1/swagger.json", "My API V1");
                });

            }

        }
    }
}
