using AutoMapper;
using CSRedis;
using FluentValidation;
using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NLog.Extensions.Logging;
using NLog.Web;
using Performance.DtoModels.AppSettings;
using Performance.DtoModels.AutoMapper;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Services;
using System.Globalization;
using System.Reflection;
using System.Text;

namespace Performance.Extract.Api
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //LogHelper.Initialize(Configuration.GetSection("AppConnection:RedisConnectionString").Value, "MTEzMTAyMzEzNDYzMzY5MzE4NA");
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

            #region appsetting注入
            services
                .Configure<AppConnection>(Configuration.GetSection("AppConnection"))
                .Configure<Application>(Configuration.GetSection("Application"))
                .Configure<EmailOptions>(Configuration.GetSection("EmailOptions"))
                .Configure<WebapiUrl>(Configuration.GetSection("WebapiUrl"));
            #endregion

            var connection = services.BuildServiceProvider().GetService<IOptions<AppConnection>>();

            #region json & fluentvalidation & filter
            services
                //筛选器配置
                .AddControllers(option =>
                {
                    option.Filters.Add<ExceptionsFilter>();
                })
                .AddNewtonsoftJson(json =>
                {
                    json.SerializerSettings.Converters.Add(new IsoDateTimeConverterContent() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
                    json.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
                    json.SerializerSettings.ContractResolver = new LowercaseContractResolver();
                    json.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Include;
                    json.SerializerSettings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
                    json.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
                    json.SerializerSettings.Culture = new CultureInfo("it-IT");
                    json.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
                })
                //model验证
                .AddFluentValidation(fv =>
                {
                    //禁用其他以使FluentValidation是唯一执行的验证库
                    fv.RunDefaultMvcValidationAfterFluentValidationExecutes = false;

                    var assembly = Assembly.Load("Performance.DtoModels");
                    var types = ReflectionHelper.GetInstances<IValidator>(assembly);
                    foreach (var type in types)
                    {
                        fv.RegisterValidatorsFromAssemblyContaining(type.GetType());
                    }
                });
            #endregion


            #region service注入 repoitory注入 
            services
                .AddPerformanceService()
                .AddPerformanceRepoitory();
            #endregion

            services.AddAutoMapper(typeof(AutoMapperConfigs));
            RedisHelper.Initialization(new CSRedisClient(connection.Value.RedisConnectionString));

            #region email

            //阿里邮箱配置
            var emailOption = services.BuildServiceProvider().GetService<IOptions<EmailOptions>>();
            //邮件发送
            services.AddEmailUtil(options =>
            {
                options.Account = emailOption.Value.Account;
                options.Password = emailOption.Value.Password;
                options.SmtpServer = emailOption.Value.SmtpServer;
            });

            #endregion

            services.AddDbContext<PerformanceDbContext>(options =>
            {
                options.UseMySql(connection.Value.PerformanceConnectionString, ServerVersion.AutoDetect(connection.Value.PerformanceConnectionString));
            });
            services.AddSignalR();
            services.AddCors(options =>
            {
                options.AddPolicy("SignalrCore", policy =>
                {
                    policy.SetIsOriginAllowed(origin => true).AllowAnyHeader().AllowAnyMethod().AllowCredentials();
                });
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseCors("SignalrCore");
            loggerFactory.CreateLogger<Startup>().LogDebug(env.EnvironmentName);

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
                endpoints.MapHub<AllotLogHub>("/allotLogHub");
            });
        }
    }
}
