using DataSharing.LuZhou.LuZhou110;
using DataSharing.Province.SendTask;
using DataSharing.Repository;
using DataSharing.SendTask;
using Mapster;
using MapsterMapper;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Quartz;
using Quartz.AspNetCore;
using System.Text;
using XF.Domain.Entities;
using XF.Domain.Exceptions;
using XF.Domain.Options;
using XF.Domain.Repository;

namespace DataSharing.Host
{
    /// <summary>
    /// 
    /// </summary>
    public static class StartupHelper
    {
        /// <summary>
        /// Authentication
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static IServiceCollection RegisterAuthentication(this IServiceCollection services, ConfigurationManager configuration)
        {
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                 .AddJwtBearer(d =>
                 {
                     var jwtOptions = configuration.GetSection("IdentityConfiguration").Get<IdentityConfiguration>().Jwt;
                     byte[] bytes = Encoding.UTF8.GetBytes(jwtOptions.SecretKey);
                     var secKey = new SymmetricSecurityKey(bytes);
                     d.TokenValidationParameters = new()
                     {
                         ValidateIssuer = false,
                         ValidateAudience = false,
                         ValidateLifetime = true,
                         ValidateIssuerSigningKey = true,
                         IssuerSigningKey = secKey,
                     };

                     //d.Audience = "hotline_api";
                 })
                 ;

            return services;
        }

        /// <summary>
        /// Swagger
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection RegisterSwagger(this IServiceCollection services)
        {
            services.AddSwaggerGen(c =>
            {
                //添加文档
                c.SwaggerDoc("v1", new OpenApiInfo() { Title = "Hotline Api", Version = "v1.0", Description = "城市热线api" });
                var files = Directory.GetFiles(AppContext.BaseDirectory).Where(d => d.EndsWith(".xml"));
                foreach (var file in files)
                {
                    c.IncludeXmlComments(file, true);
                }

                var scheme = new OpenApiSecurityScheme()
                {
                    Description = "Authorization header. \r\nExample: 'Bearer ***'",
                    Reference = new OpenApiReference
                    {
                        Type = ReferenceType.SecurityScheme,
                        Id = "Authorization"
                    },
                    Scheme = "oauth2",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey,
                };
                c.AddSecurityDefinition("Authorization", scheme);
                var requirement = new OpenApiSecurityRequirement();
                requirement[scheme] = new List<string>();
                c.AddSecurityRequirement(requirement);
            });

            return services;
        }

        /// <summary>
        /// Cors
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <param name="corsOrigins"></param>
        /// <returns></returns>
        public static IServiceCollection RegisterCors(this IServiceCollection services, ConfigurationManager configuration, string corsOrigins)
        {
            services.AddCors(options =>
            {
                options.AddPolicy(name: corsOrigins,
                    builder =>
                    {
                        var origins = configuration.GetSection("Cors:Origins").Get<string[]>();
                        builder.SetIsOriginAllowed(a =>
                            {
                                return origins.Any(origin => origin.StartsWith("*.", StringComparison.Ordinal)
                                    ? a.EndsWith(origin[1..], StringComparison.Ordinal)
                                    : a.Equals(origin, StringComparison.Ordinal));
                            })
                            .AllowAnyHeader()
                            .AllowAnyMethod()
                            .AllowCredentials();
                    });
            });

            return services;
        }

        /// <summary>
        /// Mapper
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection RegisterMapper(this IServiceCollection services)
        {
            var config = TypeAdapterConfig.GlobalSettings;
            config.ForDestinationType<IDataPermission>()
                .Ignore(d => d.CreatorId)
                .Ignore(d => d.CreatorOrgId)
                //.Ignore(d => d.CreatorOrgCode)
                .Ignore(d => d.AreaId);
            config.ForDestinationType<IWorkflow>()
                .Ignore(d => d.ExpiredTimeConfigId);
            config.ForDestinationType<IHasCreationTime>()
                .Ignore(d => d.CreationTime);
            config.ForDestinationType<IHasDeletionTime>().Ignore(d => d.DeletionTime);
            config.ForDestinationType<ISoftDelete>().Ignore(d => d.IsDeleted);
            config.ForDestinationType<IHasModificationTime>().Ignore(d => d.LastModificationTime);
            config.ForDestinationType<Entity>().Ignore(d => d.Id);

            services.AddSingleton(config);
            services.AddScoped<IMapper, ServiceMapper>();

            return services;
        }

        /// <summary>
        /// SignalR
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static IServiceCollection RegisterSignalR(this IServiceCollection services, ConfigurationManager configuration)
        {
            var connectionString = configuration.GetConnectionString("Redis");
            if (string.IsNullOrEmpty(connectionString))
                throw new UserFriendlyException("未配置signalR的redis连接");
            services.AddSignalR().AddStackExchangeRedis(connectionString, options =>
            {
                options.Configuration.ChannelPrefix = "Hotline:signalr:";
            });

            return services;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection RegisterRepository(this IServiceCollection services)
        {
            services.AddScoped(typeof(IRepository<>), typeof(BaseRepository<>));

            return services;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection RegisterJob(this IServiceCollection services, SharingConfiguration sharingConfig)
        {
            services.AddQuartz(d =>
            {
                d.SchedulerId = "scheduler1";
                d.InterruptJobsOnShutdown = true;
                d.InterruptJobsOnShutdownWithWait = true;
                d.MaxBatchSize = 3;

                //服务工单受理  
                var taskSubmitCaseInfoJobKey = new JobKey("task-submit-case-info-job", "task submit case info job");
                d.AddJob<TaskSubmitCaseInfoJob>(taskSubmitCaseInfoJobKey);
                d.AddTrigger(t => t
                    .WithIdentity("task-submit-case-info-trigger")
                    .ForJob(taskSubmitCaseInfoJobKey)
                    .StartNow()
                    .WithCronSchedule("0/15 * * * * ? ")
                );

                //服务工单处理过程
                var taskSubmitCaseProcessKey = new JobKey("task-submit-case-process-job", "task submit case process job");
                d.AddJob<TaskSubmitCaseProcessJob>(taskSubmitCaseProcessKey);
                d.AddTrigger(t => t
                    .WithIdentity("task-submit-case-process-trigger")
                    .ForJob(taskSubmitCaseProcessKey)
                    .StartNow()
                  .WithCronSchedule("0/30 * * * * ? ")
                );

                //服务工单处理结果
                var taskSubmitCaseResultKey = new JobKey("task-submit-case-result-job", "task submit case result job");
                d.AddJob<TaskSubmitCaseResultJob>(taskSubmitCaseResultKey);
                d.AddTrigger(t => t
                    .WithIdentity("task-submit-case-result-trigger")
                    .ForJob(taskSubmitCaseResultKey)
                    .StartNow()
                    .WithCronSchedule("0/30 * * * * ? ")
                );

                //电话记录
                var taskSubmitCaseRecordKey = new JobKey("task-submit-case-record-job", "task submit case record job");
                d.AddJob<TaskSubmitCaseRecordJob>(taskSubmitCaseRecordKey);
                d.AddTrigger(t => t
                    .WithIdentity("task-submit-case-record-trigger")
                    .ForJob(taskSubmitCaseRecordKey)
                    .StartNow()
                    .WithCronSchedule("0/15 * * * * ? ")
                );

                //回访记录
                var taskSubmitVisitInfoKey = new JobKey("task-submit-visit-info-job", "task submit visit info job");
                d.AddJob<TaskSubmitVisitInfoJob>(taskSubmitVisitInfoKey);
                d.AddTrigger(t => t
                    .WithIdentity("task-submit-visit-info-trigger")
                    .ForJob(taskSubmitVisitInfoKey)
                    .StartNow()
                    .WithCronSchedule("0/30 * * * * ? ")
                );

                //省推送其他服务
                var taskProvinceOtherKey = new JobKey("task-province-other-job", "task province other job");
                d.AddJob<TaskProvinceOtherJob>(taskProvinceOtherKey);
                d.AddTrigger(t => t
                    .WithIdentity("task-province-other-trigger")
                    .ForJob(taskProvinceOtherKey)
                    .StartNow()
                   .WithCronSchedule("0/30 * * * * ? ")
                );

                //其它平台服务
                var taskOtherPlatformsKey = new JobKey("task-other-platforms-job", "task other platforms job");
                d.AddJob<TaskOtherPlatformsJob>(taskOtherPlatformsKey);
                d.AddTrigger(t => t
                    .WithIdentity("task-other-platforms-trigger")
                    .ForJob(taskOtherPlatformsKey)
                    .StartNow()
                    .WithCronSchedule("0/30 * * * * ? ")
                );

                //再次电话记录
                var tasksendcallKey = new JobKey("task-send-call-job", "task send call job");
                d.AddJob<TaskSendCallJob>(tasksendcallKey);
                d.AddTrigger(t => t
                    .WithIdentity("task-send-call-trigger")
                    .ForJob(tasksendcallKey)
                    .StartNow()
                    .WithCronSchedule("0/30 * * * * ? ")
                );

                if (sharingConfig != null && sharingConfig.CityCode == ConfigurationConsts.LuZhou)//泸州
                {
                    //泸州110推送工单
                    var taskSendTaskLuZhou110Key = new JobKey("task-send-luzhou110-job", "task send luzhou110 job");
                    d.AddJob<TaskSendTaskLuZhou110Job>(taskSendTaskLuZhou110Key);
                    d.AddTrigger(t => t
                        .WithIdentity("task-send-luzhou110-trigger")
                        .ForJob(taskSendTaskLuZhou110Key)
                        .StartNow()
                        .WithCronSchedule("0/30 * * * * ? ")
                    );
                }

                ////execute send task
                //var taskExecuteJobKey = new JobKey("task-execute-job", "send task");
                //d.AddJob<TaskExecuteJob>(taskExecuteJobKey);

                //d.AddTrigger(t => t
                //    .WithIdentity("task-execute-trigger")
                //    .ForJob(taskExecuteJobKey)
                //    .StartNow()
                //    .WithCronSchedule("0/1 * * * * ? ")
                //);

                //2小时定时拉取12315的办理过程
                var taskCaseDistrecordJobKey = new JobKey("task-case-distrecord-job", "task case distrecord job");
                d.AddJob<TaskCaseDistrecordJob>(taskCaseDistrecordJobKey);
                d.AddTrigger(t => t
                    .WithIdentity("task-case-distrecord-job-trigger")
                    .ForJob(taskCaseDistrecordJobKey)
                    .StartNow()
                    .WithCronSchedule("0 0 */2 * * ?")
                );

                ////2小时上传实时服务上报
                //var taskSendRealTimeStatusJobKey = new JobKey("task-send-realtime-status-job", "task send realtime status job");
                //d.AddJob<TaskSendRealTimeStatusJob>(taskSendRealTimeStatusJobKey);
                //d.AddTrigger(t => t
                //    .WithIdentity("task-send-realtime-status-trigger")
                //    .ForJob(taskSendRealTimeStatusJobKey)
                //    .StartNow()
                //    .WithCronSchedule("0 0 */2 * * ?")
                //);

                ////每天凌晨1点推送业务汇聚-统计数据
                //var taskSubmitCaseTotalJobKey = new JobKey("task-submit-case-total-job", "task submit case total job");
                //d.AddJob<TaskSubmitCaseTotalJob>(taskSubmitCaseTotalJobKey);
                //d.AddTrigger(t => t
                //    .WithIdentity("task-submit-case-total-job-trigger")
                //    .ForJob(taskSubmitCaseTotalJobKey)
                //   .StartNow()
                //    .WithCronSchedule("0 0 1 * * ?")//0 0 1 * * ?
                //);

                ////每天晚上23点处理每天办理完成未及时推送办理结果的数据
                //var taskRepublishFiledOrdersJobKey = new JobKey("task-republish-filed-orders-job", "task republish filed orders job");
                //d.AddJob<TaskRepublishFiledOrdersJob>(taskRepublishFiledOrdersJobKey);
                //d.AddTrigger(t => t
                //    .WithIdentity("task-republish-filed-orders-job-trigger")
                //    .ForJob(taskRepublishFiledOrdersJobKey)
                //   .StartNow()
                //   .WithCronSchedule("0 0 23 * * ?")//0 0 1 * * ?
                //);

                ////每天晚上23点处理未关联工单的通话记录
                //var taskAssociateCallRecordsJobKey = new JobKey("task-associate-call-records-job", "task associate call records job");
                //d.AddJob<TaskAssociateCallRecordsJob>(taskAssociateCallRecordsJobKey);
                //d.AddTrigger(t => t
                //    .WithIdentity("task-associate-call-records-job-trigger")
                //    .ForJob(taskAssociateCallRecordsJobKey)
                //   .StartNow()
                //   .WithCronSchedule("0 0 23 * * ?")//0 0 1 * * ?
                //);

                ////每天晚上23点50处理未查询到通话记录的工单，修改为其他来源
                //var TaskGetOrderMatchingCallListJobKey = new JobKey("task-get-order-matching-call-list-job-job", "task get order matching call list job");
                //d.AddJob<TaskGetOrderMatchingCallListJob>(TaskGetOrderMatchingCallListJobKey);
                //d.AddTrigger(t => t
                //    .WithIdentity("task-get-order-matching-call-list-job-trigger")
                //    .ForJob(TaskGetOrderMatchingCallListJobKey)
                //   .StartNow()
                //   .WithCronSchedule("0 50 23 * * ?")//0 0 1 * * ?
                //);

            });


            services.AddQuartzServer(d =>
            {
                d.WaitForJobsToComplete = true;
                d.StartDelay = TimeSpan.FromSeconds(5);
            });

            return services;
        }
    }
}
