using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using System.Text;
using System.Security.Claims;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.AspNetCore.Authorization;
using NLog.Extensions.Logging;
using NLog.Web;
using Microsoft.AspNetCore.Mvc.Versioning;
using MadRunFabric.Common.Options;
using CallCenterApi.IRepositories;
using CallCenterApi.Repositories;
using Pivotal.Discovery.Client;
using Api.SignToken;
using AutoMapper;
using SignTokenApi.IRepositories;
using SignTokenApi.Repositories;
using CallCenterApi.Model;
using Microsoft.EntityFrameworkCore;
using WorkOrderApi.IRepositories;
using WorkOrderApi.Repositories;
using ConfigurationApi.IRepositories;
using ConfigurationApi.Repositories;

namespace CallCenterApi
{
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            Configuration = new ConfigurationBuilder()
                            .SetBasePath(env.ContentRootPath)
                            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
                            .AddEnvironmentVariables()
                            .Build();
        }

        public IConfiguration Configuration { get; }


        public void ConfigureServices(IServiceCollection services)
        {
            #region Cors配置
            services.AddCors(options =>
            {
                options.AddPolicy("CorsProd",
                 builder => builder.AllowAnyOrigin()
                //builder => builder.WithOrigins(Configuration["Cors"].Split(','))
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials()
                .SetPreflightMaxAge(TimeSpan.FromMinutes(30)));
            });

            services.AddCors(options =>
            {
                options.AddPolicy("CorsDev",
                builder => builder.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader()
                .AllowCredentials()
                .SetPreflightMaxAge(TimeSpan.FromMinutes(30)));
            });
            #endregion

            #region 授权配置
            //读取jwt配置文件
            var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:SecretKey"].ToString()));
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = signingKey,
                ValidateIssuer = true,
                ValidIssuer = Configuration["Jwt:Issuer"].ToString(),//发行人
                ValidateAudience = true,
                ValidAudience = Configuration["Jwt:Audience"].ToString(),//订阅人
                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero,
                RequireExpirationTime = true,
            };


            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(o =>
            {
                //不使用https
                o.RequireHttpsMetadata = false;
                o.TokenValidationParameters = tokenValidationParameters;
                o.Events = new JwtBearerEvents
                {
                    OnTokenValidated = context =>
                    {
                        if (context.Request.Path.Value.ToString() == "/api/logout")
                        {
                            var token = ((context as TokenValidatedContext).SecurityToken as JwtSecurityToken).RawData;
                        }
                        return Task.CompletedTask;
                    }
                };
            });
            #endregion

            #region redis配置
            services.AddDistributedRedisCache(options =>
            {
                options.InstanceName = Configuration["Redis:InstanceName"].ToString();
                options.Configuration = $"{Configuration["Redis:HostName"].ToString()}:{Configuration["Redis:Port"].ToString()},allowAdmin=true,password={Configuration["Redis:Password"].ToString()},defaultdatabase={Configuration["Redis:Defaultdatabase"].ToString()}";
            });
            #endregion

            #region configuration
            services.AddSingleton<IConfiguration>(Configuration);
            #endregion

            //注入授权Handler
            services.AddSingleton<IAuthorizationHandler, PermissionAuthorizationHandler>();

            services.AddSingleton<IPermissionService, PermissionService>();
            services.AddSingleton<ISignTokenService, SignTokenService>();
            #region 版本控制
            services.AddApiVersioning(Options =>
            {
                Options.ReportApiVersions = true;//可选，为true API返回响应标头中支持的版本信息
                Options.ApiVersionReader = new QueryStringApiVersionReader(parameterName: "api-version");
                Options.AssumeDefaultVersionWhenUnspecified = true;
                Options.DefaultApiVersion = new Microsoft.AspNetCore.Mvc.ApiVersion(6, 0);
            });
            #endregion

            ////建议不再过滤器中记录日志，官网建议
            //services.AddMvc(options =>
            //{
            //    options.Filters.Add(typeof(ErrorAsyncExceptionFilter));
            //})
            //    .AddJsonOptions(op => op.SerializerSettings.ContractResolver =
            //                            new Newtonsoft.Json.Serialization.DefaultContractResolver());


            #region steeltoe
            services.AddDiscoveryClient(Configuration);
            #endregion


            #region AutoMapper
            services.AddAutoMapper();
            #endregion

            services.AddMvc().AddJsonOptions(op => op.SerializerSettings.ContractResolver =
                                       new Newtonsoft.Json.Serialization.DefaultContractResolver());

            #region PostgreSQL配置
            //services.Configure<DbOptions>(options =>
            //{
            //    options.ConnectionString = Configuration.GetSection("PostgreSQLConnection:ConnectionString").Value;
            //    //options.ModelAssemblyName = "Zxw.Framework.Website.Models";
            //});

            services.AddDbContext<madrunfabircdb_baseContext>(option => option.UseNpgsql(Configuration.GetSection("PostgreSQLConnection:ConnectionString").Value));
            #endregion

            #region Mongodb配置
            services.Configure<MongodbOptions>(options =>
            {
                options.ConnectionString = Configuration.GetSection("MongoConnection:ConnectionString").Value;
                options.Database = Configuration.GetSection("MongoConnection:Database").Value;
            });
            #endregion

            #region 添加仓储访问服务
            services.AddTransient<ICall_AutoCallNumRepository, Call_AutoCallNumRepository>();
            services.AddTransient<ICall_BlacklistRepository, Call_BlacklistRepository>();
            services.AddTransient<ICall_DutyPhoneRepository, Call_DutyPhoneRepository>();
            services.AddTransient<ISys_IVRWordsRepository, Sys_IVRWordsRepository>();
            services.AddTransient<IRepositories.ISys_SystemConfigRepository, Repositories.Sys_SystemConfigRepository>();
            services.AddTransient<ISys_SeatGroupRepository, Sys_SeatGroupRepository>();
            services.AddTransient<ISys_WorkOFFDaysRepository, Sys_WorkOFFDaysRepository>();
            services.AddTransient<ISys_WorkTimesRepository, Sys_WorkTimesRepository>();
            services.AddTransient<ISys_TelTitleDataRepository, Sys_TelTitleDataRepository>();
            //2018-7-12
            services.AddTransient<IMW_Agent_Callout_RecordRepository, MW_Agent_Callout_RecordRepository>();
            services.AddTransient<IMW_Agent_Conference_RecordRepository, MW_Agent_Conference_RecordRepository>();
            services.AddTransient<IMW_Agent_State_RecordRepository, MW_Agent_State_RecordRepository>();
            services.AddTransient<IMW_Agent_Transfer_RecordRepository, MW_Agent_Transfer_RecordRepository>();
            services.AddTransient<IMW_Autocall_Call_RecordRepository, MW_Autocall_Call_RecordRepository>();
            services.AddTransient<IMW_Ext_Callin_RecordRepository, MW_Ext_Callin_RecordRepository>();
            services.AddTransient<IMW_Trunk_Callin_RecordRepository, MW_Trunk_Callin_RecordRepository>();
            services.AddTransient<IMW_Agent_Repose_RecordRepository, MW_Agent_Repose_RecordRepository>();
            services.AddTransient<ICall_RecordsRepository, Call_RecordsRepository>();
            services.AddTransient<IMW_IVR_Callout_RecordRepository, MW_IVR_Callout_RecordRepository>();
            services.AddTransient<IMW_Leave_RecordRepository, MW_Leave_RecordRepository>();

            services.AddTransient<ICall_OutTaskRepository, Call_OutTaskRepository>();
            services.AddTransient<ICall_OutTaskTelNumRepository, Call_OutTaskTelNumRepository>();
            services.AddTransient<ICall_MobileDataRepository, Call_MobileDataRepository>();
            services.AddTransient<SignTokenApi.IRepositories.ISys_User_AccountRepository, SignTokenApi.Repositories.Sys_User_AccountRepository>();
            services.AddTransient<ICall_OutTaskFPRepository, Call_OutTaskFPRepository>();
            services.AddTransient<ICall_OutTaskTelNumRecordRepository, Call_OutTaskTelNumRecordRepository>();

            services.AddTransient<IBus_Order_BaseRepository, Bus_Order_BaseRepository>();
            services.AddTransient<IBus_Order_ItemRepository, Bus_Order_ItemRepository>();

            services.AddTransient<ICus_User_BaseRepository, Cus_User_BaseRepository>();

            services.AddTransient<IKnowledge_BaseRepository, Knowledge_BaseRepository>();
            services.AddTransient<IKnowledge_TypeRepository, Knowledge_TypeRepository>();
            services.AddTransient<ISys_IVRConfigsRepository, Sys_IVRConfigsRepository>();
            services.AddTransient<ISys_IVRConfigsLogRepository, Sys_IVRConfigsLogRepository>();

            services.AddTransient<IQC_CheckTypeRepository, QC_CheckTypeRepository>();
            services.AddTransient<IQC_CheckScoreRepository, QC_CheckScoreRepository>();
            services.AddTransient<IQC_CheckListRepository, QC_CheckListRepository>();

            services.AddTransient<IAsk_QuestionPagerRepository, Ask_QuestionPagerRepository>();
            services.AddTransient<IAsk_QuestionRepository, Ask_QuestionRepository>();
            services.AddTransient<IAsk_QuestionItemsRepository, Ask_QuestionItemsRepository>();
            services.AddTransient<IAsk_QuestionListRepository, Ask_QuestionListRepository>();

            services.AddTransient<IBus_WorkOrder_BaseRepository, Bus_WorkOrder_BaseRepository>();
            
            services.AddTransient<ICus_Customer_ProjectRepository, Cus_Customer_ProjectRepository>();
            services.AddTransient<ICall_ClickOutTaskTelNumRepository, Call_ClickOutTaskTelNumRepository>();

            services.AddTransient<ISys_ProvincesRepository, Sys_ProvincesRepository>();
            services.AddTransient<ISys_CityRepository, Sys_CityRepository>();

            #endregion
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            if (env.IsProduction())
            {
                app.UseCors("CorsProd");
            }
            else
            {
                app.UseCors("CorsDev");
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
                app.UseBrowserLink();
            }

            app.UseAuthentication();

            app.UseMvc();

            #region steeltoe
            app.UseDiscoveryClient();
            #endregion

            #region Nlog 引入
            loggerFactory.AddNLog();//添加NLog
            env.ConfigureNLog("nlog.config");//读取Nlog配置文件
            app.AddNLogWeb();
            #endregion
        }
    }
}
