using Furion;
using Furion.Schedule;
using Furion.VirtualFileServer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using System.Text.Json;
using System.Text.Json.Serialization;
using YBEE.EQM.Application;
using YBEE.EQM.Core;

namespace YBEE.EQM.Web.Core;

public class Startup : AppStartup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddResponseCompression();
        services.AddConsoleFormatter();
        services.AddJwt<JwtHandler>(enableGlobalAuthorize: true);
        services.AddConfigurableOptions<AuthOptions>();
        services.AddConfigurableOptions<RefreshTokenSettingOptions>();
        services.AddConfigurableOptions<EqmSiteOptions>();

        services.AddCorsAccessor();
        services.AddRemoteRequest();

        services.AddControllers()
            .AddJsonOptions(options =>
            {
                // 日期时间类型格式化
                options.JsonSerializerOptions.Converters.AddDateTimeTypeConverters("yyyy-MM-dd HH:mm:ss");
                // 忽略循环引用
                options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
                // 包含成员字段序列化
                options.JsonSerializerOptions.IncludeFields = true;
                // 允许尾随逗号
                options.JsonSerializerOptions.AllowTrailingCommas = true;
                // 允许注释
                options.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip;
                // long 转 string
                options.JsonSerializerOptions.Converters.AddLongTypeConverters();

                options.JsonSerializerOptions.PropertyNameCaseInsensitive = false;
                options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;

            })
            .AddInjectWithUnifyResult<XnRestfulResultProvider>()
            .AddMvcFilter<RequestActionFilter>();

        services.Configure<FormOptions>(x =>
        {
            x.ValueLengthLimit = int.MaxValue;
            x.MultipartBoundaryLengthLimit = int.MaxValue;
        });

        //services.AddSwaggerGen(options =>
        //{
        //    options.DescribeAllParametersInCamelCase();
        //});

        services.AddSnowflakeId(); // 雪花ID

        // 注册EventBus服务
        services.AddEventBus(builder =>
        {
            // 注册 Log 日志订阅者
            builder.AddSubscriber<LogEventSubscriber>();
        });

        // 注册作业调度
        services.AddSchedule(options =>
        {
            if (int.TryParse(App.Configuration["EqmSite:SyncQuestionnaireIntervalMinute"], out int m))
            {
                options.LogEnabled = false;
                var triggerBuilder = Triggers.PeriodMinutes(m).SetRunOnStart(true).SetTriggerId($"patriarch_questionnaire_progress_sync_{m}m");
                options.AddJob<ExamPatriarchQuestionnaireProgressSyncJob>("patriarch_questionnaire_progress_sync", concurrent: false, triggerBuilder);
            }
        });
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        // 添加状态码拦截中间件，处理 401、403 等
        app.UseUnifyResultStatusCodes();

        if (!env.IsDevelopment())
        {
            //app.UseHttpsRedirection();
        }

        app.UseResponseCompression();
        app.UseStaticFiles(new StaticFileOptions
        {
            ContentTypeProvider = FS.GetFileExtensionContentTypeProvider()
        });

        app.UseScheduleUI(options =>
        {
            options.RequestPath = "/sync-jobs";
        });

        //// 如果目录不存在则创建
        //var option = App.GetOptions<EqmSiteOptions>();
        //var staticRoot = Path.Combine(option.ExamResultRoot, option.RequestPath); // 注意这里不要添加 /
        //if (!Directory.Exists(staticRoot)) Directory.CreateDirectory(staticRoot);
        //app.UseFileServer(new FileServerOptions
        //{
        //    RequestPath = $"/{option.RequestPath}",   // 配置访问地址，需以 / 开头，通常和目录名称一致，也可以不同
        //    FileProvider = new PhysicalFileProvider(staticRoot),
        //    EnableDirectoryBrowsing = false,
        //});

        // Serilog请求日志中间件---必须在 UseStaticFiles 和 UseRouting 之间
        app.UseSerilogRequestLogging();

        app.UseRouting();

        app.UseCorsAccessor();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseInject(string.Empty);

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapFallbackToFile("index.html");
        });
    }
}