using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.IRepositories;
using System.Linq;
using System.Repositories;
using System.Text;
using System.Threading.Tasks;
using System.Common;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using NLog.Extensions.Logging;
using NLog.Web;
using SignToken;
using Steeltoe.Discovery.Client;
using Microsoft.Extensions.FileProviders;
using System.IO;
using Microsoft.AspNetCore.Http;
using Hangfire;
using TVShoppingCallCenter_ZLJ.Controllers.hangfire;
using SqlSugar;
using Hangfire.MySql.Core;
using System.Data;
using System.Repositories.Sys;
using System.IRepositories.Sys;
using System.IRepositories.Call;
using System.Repositories.Call;

namespace TVShoppingCallCenter_ZLJ
{
    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)
        {
            #region Cors 配置
            services.AddCors(options =>
            {
                options.AddPolicy("Cors",//CorsPolicy
                builder => builder.AllowAnyOrigin()//builder.WithOrigins(Configuration["Cors"].Split(','))
                .AllowAnyMethod()
                .SetIsOriginAllowed(_ => true)//上线后删除此行 加入域列表 内网可忽略
                .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 =>
            {
                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 配置数据库
            BaseContext.DB_ConnectionString = Configuration.GetConnectionString("DefaultConnection");
            BaseMysqlContext.DB_ConnectionString = Configuration.GetConnectionString("MySqlConnection");
            #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 注入
            services.AddSingleton<IConfiguration>(Configuration);
            //services.AddSingleton<IAuthorizationHandler, PermissionAuthorizationHandler>();
            //services.AddSingleton<IPermissionService, PermissionService>();

            services.AddTransient<ISys_UserAccountRepository, Sys_UserAccountRepository>();
            services.AddTransient<ISys_RoleInfoRepository, Sys_RoleInfoRepository>();
            services.AddTransient<ISys_SeatGroupRepository, Sys_SeatGroupRepository>();
            services.AddTransient<ISys_LoginLogsRepository, Sys_LoginLogsRepository>();

            services.AddTransient<ISys_DepartmentRepository, Sys_DepartmentRepository>();
            services.AddTransient<ISys_DictionaryValueRepository, Sys_DictionaryValueRepository>();
            services.AddTransient<ISys_ModuleButtonInfoRepository, Sys_ModuleButtonInfoRepository>();
            services.AddTransient<ISys_ModuleInfoRepository, Sys_ModuleInfoRepository>();
            services.AddTransient<ISys_RoleFunctionRepository, Sys_RoleFunctionRepository>();
            services.AddTransient<ISys_SeatPermissionConfigRepository, Sys_SeatPermissionConfigRepository>();
            services.AddTransient<ISys_SystemConfigRepository, Sys_SystemConfigRepository>();
            services.AddTransient<ISys_MobileDataRepository, Sys_MobileDataRepository>();
            services.AddTransient<ISys_WorkOffDaysRepository, Sys_WorkOffDaysRepository>();
            services.AddTransient<ISys_WorkTimesRepository, Sys_WorkTimesRepository>();
            services.AddTransient<ISys_AreaRepository, Sys_AreaRepository>();
            services.AddTransient<ISys_CallDutyNumberRepository, Sys_CallDutyNumberRepository>();
            services.AddTransient<ISys_CallBlacklistRepository, Sys_CallBlacklistRepository>();
            services.AddTransient<ISys_PositionRepository, Sys_PositionRepository>();
            services.AddTransient<ISys_DeptTeamRepository, Sys_DeptTeamRepository>();

            services.AddTransient<IBus_ProductClassRepository, Bus_ProductClassRepository>();
            services.AddTransient<IBus_ProductRepository, Bus_ProductRepository>();
            services.AddTransient<IBus_TagRepository, Bus_TagRepository>();
            services.AddTransient<IBus_OrderRepository, Bus_OrderRepository>();
            services.AddTransient<IBus_OrderDetailRepository, Bus_OrderDetailRepository>();
            services.AddTransient<IBus_StockLogRepository, Bus_StockLogRepository>();
            services.AddTransient<IBus_OrderMergeRepository, Bus_OrderMergeRepository>();
            services.AddTransient<IBus_AfterSaleRepository, Bus_AfterSaleRepository>();
            services.AddTransient<IBus_OrderMoneyRepository, Bus_OrderMoneyRepository>();
            services.AddTransient<IBus_SMSLogRepository, Bus_SMSLogRepository>();
            services.AddTransient<IBus_SMSTemplateRepository, Bus_SMSTemplateRepository>();
            services.AddTransient<ICall_CallRecordsRepository, Call_CallRecordsRepository>();
            services.AddTransient<ICDRRepository, CDRRepository>(); 
            services.AddTransient<ISysUser_GradeRepository, SysUser_GradeRepository>();
            services.AddTransient<ISysUser_TeamGradeRepository, SysUser_TeamGradeRepository>();

            services.AddHangfire(x => x.UseStorage(new MySqlStorage(BaseContext.DB_ConnectionString, new MySqlStorageOptions
            {
                TransactionIsolationLevel = IsolationLevel.ReadCommitted,
                QueuePollInterval = TimeSpan.FromSeconds(15),
                JobExpirationCheckInterval = TimeSpan.FromHours(1),
                CountersAggregateInterval = TimeSpan.FromMinutes(5),
                PrepareSchemaIfNecessary = true,
                DashboardJobListLimit = 50000,
                TransactionTimeout = TimeSpan.FromMinutes(1),
                TablePrefix = "Hangfire"
            })));
            //GlobalConfiguration.Configuration.UseStorage(
            //      new MySqlStorage(BaseMysqlContext.DB_ConnectionString, new MySqlStorageOptions
            //      {
            //          TransactionIsolationLevel = IsolationLevel.ReadCommitted,
            //          QueuePollInterval = TimeSpan.FromSeconds(15),
            //          JobExpirationCheckInterval = TimeSpan.FromHours(1),
            //          CountersAggregateInterval = TimeSpan.FromMinutes(5),
            //          PrepareSchemaIfNecessary = true,
            //          DashboardJobListLimit = 50000,
            //          TransactionTimeout = TimeSpan.FromMinutes(1),
            //          TablePrefix = "Hangfire_"
            //      }));
            //services.AddHangfire(x => x.UseSqlServerStorage(BaseContext.DB_ConnectionString));

            services.AddTransient<ICus_VipInfoRepository, Cus_VipInfoRepository>();
            services.AddTransient<ICus_VipLabelInfoRepository, Cus_VipLabelInfoRepository>();
            services.AddTransient<ICus_ScoreSetRepository, Cus_ScoreSetRepository>();
            services.AddTransient<ICus_MsgRepository, Cus_MsgRepository>();

            services.AddTransient<ISys_MarketingRepository, Sys_MarketingRepository>();

            services.AddTransient<ISys_MediaCenteRepository, Sys_MediaCente>();
            services.AddTransient<ISys_MediaManagementRepository, Sys_MediaManagement>();
            services.AddTransient<ISys_PlanManagemenRepository, Sys_PlanManagemen>();

            services.AddTransient<ISys_TaskManagementRepository, Sys_TaskManagementRepository>();
            services.AddTransient<ISys_TodoManagementRepository, Sys_TodoManagementRepository>();

            services.AddTransient<ISMS_InternalMessagesReposytory, SMS_InternalMessagesReposytory>();

            services.AddTransient<IQC_IndexBaseReposytory, QC_IndexBaseReposytory>();
            services.AddTransient<IQC_IndexCategoryReposytory, QC_IndexCategoryReposytory>();

            services.AddTransient<IRepositoryCategoryRepository, RepositoryCategoryRepository>();
            services.AddTransient<IRepositoryInformationRepository, RepositoryInformationRepository>();

            services.AddTransient<ISys_AccessoriesRepository, Sys_AccessoriesRepository>();

            services.AddTransient<ISys_OutboundTaskReposity, Sys_OutboundTaskReposity>();
            services.AddTransient<ISys_AutoDialRepository, Sys_AutoDialRepository>();

            services.AddTransient<ItaskRepository, taskRepository>();
            services.AddTransient<Iauto_cdrRepository , auto_cdrRepository>();
            services.AddTransient<ICall_CallOutboundRepository, Call_CallOutboundRepository>();
            services.AddTransient<Ipoint_agentRepository, point_agentRepository>();
            services.AddTransient<ISys_BottomNumberRepository, Sys_BottomNumberRepository>();
            
            #endregion


            //services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddMvc(options =>
            {
                options.Filters.Add(new ActionFilter());
                options.Filters.Add(new ExceptionFilter());
            }).AddJsonOptions(op => op.SerializerSettings.ContractResolver =
                                        new Newtonsoft.Json.Serialization.DefaultContractResolver()).AddControllersAsServices();
            #region steeltoe
            //services.AddDiscoveryClient(Configuration);
            #endregion
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            app.UseCors("Cors");
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
            app.UseBrowserLink();
            app.UseStaticFiles(new StaticFileOptions()
            {
                FileProvider = new PhysicalFileProvider(
                Path.Combine(Directory.GetCurrentDirectory(), @"excelmod")),
                RequestPath = new PathString("/excelmod")
            });
            app.UseStaticFiles(new StaticFileOptions()
            {
                FileProvider = new PhysicalFileProvider(
                Path.Combine(Directory.GetCurrentDirectory(), @"log")),
                RequestPath = new PathString("/log")
            });
            //app.UseHttpsRedirection();
            //引入授权
            app.UseAuthentication();
            app.UseMvc();

            app.UseHangfireServer(new BackgroundJobServerOptions
            {
                Queues = new[] { "daily", "minutely", "monthly", "outbound", "autodial", "month12" },//队列名称，只能为小写
                WorkerCount = Environment.ProcessorCount * 3, //并发任务数
                ServerName = "hangfireMysql",//服务器名称
            });//启动Hangfire服务  有可选参数
            app.UseHangfireDashboard("/hangfire",
                new DashboardOptions
                {
                    Authorization = new[] { new HangfireAuthorizationFilter() }
                });//启动hangfire面板 有可选参数

            RecurringJob.AddOrUpdate<HangfireController>(a => a.DailyRecurring(), Cron.Daily, TimeZoneInfo.Local, "daily");
            RecurringJob.AddOrUpdate<HangfireController>(a => a.MinutelyRecurring(), Cron.Minutely, TimeZoneInfo.Local, "minutely");
            RecurringJob.AddOrUpdate<HangfireController>(a => a.MinutelyOutbound(), Cron.Minutely, TimeZoneInfo.Local, "outbound");
            RecurringJob.AddOrUpdate<HangfireController>(a => a.AutodialOutbound(), Cron.Minutely, TimeZoneInfo.Local, "autodial");
            //秒 分 时 日   *每
            RecurringJob.AddOrUpdate<HangfireController>(a => a.Month12Recurring(), "0 0 0 12 * ?", TimeZoneInfo.Local, "month12");
            #region steeltoe
            //app.UseDiscoveryClient();
            #endregion

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