using Alipay.EasySDK.Factory;
using Alipay.EasySDK.Kernel;
using LifePayment.Application;
using LifePayment.Domain.Shared;
using LifePayment.EntityFrameworkCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.Response;
using Volo.Abp.Auditing;
using Volo.Abp.Caching;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Identity;
using Volo.Abp.Identity.AspNetCore;
using Volo.Abp.IdentityServer.EntityFrameworkCore;
using Volo.Abp.Modularity;
using Volo.Abp.TextTemplating.Scriban;
using Volo.Abp.Threading;
using Volo.Abp.Uow;
using Volo.Abp.VirtualFileSystem;
using ZeroD.Util;

namespace LifePayment.Host
{
    [DependsOn(typeof(AbpAspNetCoreMvcModule),
               typeof(AbpBaseFrameworkModule),
               typeof(AbpEntityFrameworkCoreModule),
               typeof(LifePaymentServicesHttpApiModule),
               typeof(LifePaymentServicesEntityFrameworkCoreModule),
               typeof(LifePaymentServicesApplicationModule),
               typeof(AbpIdentityHttpApiModule),
               typeof(AbpIdentityApplicationModule),
               typeof(AbpIdentityServerEntityFrameworkCoreModule),
               typeof(AbpIdentityAspNetCoreModule), typeof(AbpTextTemplatingScribanModule))]

    public class LifePaymentServiceHostModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var configuration = context.Services.GetConfiguration();

            //Configure<AliYunSMSSettingOptions>(configuration.GetSection("AliYunSMSSetting"));
            context.Services.AddAutoMapperObjectMapper();
            ConfigurePays(context, configuration);
            context.Services.AddAuthentication("Bearer").AddIdentityServerAuthentication(options =>
            {
                options.Authority = configuration["AuthServer:Authority"];
                options.ApiName = configuration["AuthServer:ApiName"];
                options.RequireHttpsMetadata = false;
            });
            context.Services.AddCors(options =>
            {
                options.AddPolicy("cors", builder =>
                {
                    builder.WithOrigins(configuration["App:CorsOrigins"]
                           .Split(",", StringSplitOptions.RemoveEmptyEntries)
                           .Select(o => o.RemovePostFix("/")).ToArray())
                           .AllowAnyHeader()
                           .AllowAnyMethod()
                           .AllowCredentials();
                });
            });
            Configure<AbpVirtualFileSystemOptions>(options =>
            {
                options.FileSets.AddEmbedded<LifePaymentServiceHostModule>("LifePaymentServiceHost");
            });
            context.Services.AddSession();
            context.Services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new OpenApiInfo { Title = "LifePayment Service API", Version = "v1" });
                options.DocInclusionPredicate((docName, description) => true);
                options.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme()
                {
                    Description = "\"Authorization: Bearer {token}\"",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey,
                });
                options.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearerAuth" },
                        },
                        new[] { "Bearer", "Basic" }
                    },
                });
                var xmlFile = "LifePaymentService.HttpApi.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                options.IncludeXmlComments(xmlPath);
                var modelFile = "LifePaymentServices.Application.Contracts.xml";
                var modelPath = Path.Combine(AppContext.BaseDirectory, modelFile);
                options.IncludeXmlComments(modelPath);
            });
            Configure<AbpDistributedEntityEventOptions>(options => { });
            Configure<AbpDbContextOptions>(options =>
            {
                // options.UseMySQL();
                options.UseSqlServer();

            });
            context.Services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = configuration["Redis:Configuration"];
            });
            Configure<AbpAuditingOptions>(options =>
            {
                options.IsEnabledForGetRequests = true;
                options.ApplicationName = "LifePaymentService";
            });
            Configure<AbpUnitOfWorkOptions>(options =>
            {
                options.IsolationLevel = System.Data.IsolationLevel.Snapshot;
            });
            //context.Services.AddMiniProfiler(options =>
            //{
            //    options.RouteBasePath = "/profiler";
            //    (options.Storage as MemoryCacheStorage).CacheDuration = TimeSpan.FromMinutes(60);
            //    options.SqlFormatter = new StackExchange.Profiling.SqlFormatters.InlineFormatter();
            //    options.TrackConnectionOpenClose = true;
            //    options.ColorScheme = StackExchange.Profiling.ColorScheme.Auto;
            //    options.EnableMvcFilterProfiling = true;
            //    options.EnableMvcViewProfiling = true;
            //}).AddEntityFramework();
            context.Services.AddMvc(options =>
            {
                options.Filters.AddService(typeof(DataColumnActionFilter));
                options.Filters.RemoveAll(r => (r as ServiceFilterAttribute)?.ServiceType?.Name == nameof(AbpNoContentActionFilter)).FirstOrDefault();
                options.OutputFormatters.RemoveType(typeof(HttpNoContentOutputFormatter));
            }).AddXmlSerializerFormatters();
            var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
            context.Services.AddDataProtection().PersistKeysToStackExchangeRedis(redis, "LifePaymentServices-DataProtection-Keys");
            context.Services.Configure<AbpDistributedCacheOptions>(cacheOptions =>
            {
                cacheOptions.KeyPrefix = "LifePaymentServices_";
                cacheOptions.GlobalCacheEntryOptions.SlidingExpiration = TimeSpan.FromMinutes(20);
            });
            this.Configure<OssSettings>(configuration.GetSection("ossSettings"));
            this.Configure<ACOOLYOption>(configuration.GetSection("ACOOLY"));
            this.Configure<Config>("AliPayEcsign", configuration.GetSection("AliPayEcsign"));
            this.Configure<InformationOption>(configuration.GetSection("WeiXinCgi"));
            this.Configure<InitSetting>(configuration.GetSection("InitSetting"));
        }

        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();
            app.UseCors("cors");
            app.UseSession();
            //app.UseMiniProfiler();
            app.UseCorrelationId();
            //app.UseVirtualFiles();
            app.UseStaticFiles();
            app.UseAuthentication();
            app.UseRouting();
            app.UseIdentityServer();
            app.UseAuthorization();
            app.UseAbpClaimsMap();
#if DEBUG
            app.UseSwagger();
            app.UseSwaggerUI(options =>
            {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "LifePayment Service API");
            });
#endif
            app.UseAuditing();
            app.UseConfiguredEndpoints();
            AsyncHelper.RunSync(async () =>
            {
                using (var scope = context.ServiceProvider.CreateScope())
                {
                    //await scope.ServiceProvider
                    //     .GetRequiredService<IDataSeeder>()
                    //     .SeedAsync();
                }
            });
        }

        private void ConfigurePays(ServiceConfigurationContext context, IConfiguration configuration)
        {
            Configure<WxPayOption>(configuration.GetSection("WxPay"));
            context.Services.AddHttpClient(LifePaymentConstant.WxPayHttpClientName, config =>
            {
                config.Timeout = TimeSpan.FromSeconds(120);
                config.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
                config.DefaultRequestHeaders.Add("User-Agent", "Aop4Net");
                config.DefaultRequestHeaders.Add("Accept", "application/json");
            });
            Configure<Config>(configuration.GetSection("AliPay"));
            PostConfigure<Config>(r => { Factory.SetOptions(r); });
        }

    }
}