using Eis.Infrastructure.Authentication;
using Eis.Infrastructure.Administration;
using Eis.Infrastructure.Candidate;
using Eis.Infrastructure.Caching;
using Eis.Infrastructure.Configuration;
using Eis.Application.Public;
using Eis.Infrastructure;
using Eis.Infrastructure.Data;
using Eis.Infrastructure.Migration;
using Eis.Infrastructure.Security;
using Eis.Web.Configuration;
using Eis.Web.Authentication;
using Eis.Web.Administration;
using Eis.Web.Candidate;
using Eis.Web.Frontend;
using Eis.Web.Public;

var applicationRoot = ApplicationPaths.FindApplicationRoot();
EnvironmentFile.Load(applicationRoot);
var builder = WebApplication.CreateBuilder(args);

builder.WebHost.ConfigureKestrel(options => options.AddServerHeader = false);
builder.Services.AddProblemDetails();
builder.Services.AddSingleton<IPublicSiteConfiguration, PublicSiteConfiguration>();
var authenticationOptions = AuthenticationOptions.FromEnvironment(
    builder.Environment.IsProduction(),
    builder.Configuration.GetValue<bool>("AuthenticationMigration:NativeEnabled"));
var candidateMigrationOptions = CandidateMigrationOptions.FromEnvironment(
    builder.Configuration.GetValue<bool>("CandidateMigration:NativeEnabled"),
    authenticationOptions.NativeEnabled,
    authenticationOptions.SharesLegacySessions);
var adminMigrationOptions = AdminMigrationOptions.FromEnvironment(
    builder.Configuration.GetValue<bool>("AdminMigration:NativeReadsEnabled"),
    authenticationOptions.NativeEnabled,
    authenticationOptions.SharesLegacySessions,
    builder.Configuration.GetValue<bool>("AdminMigration:NativeOrganizationWritesEnabled"),
    builder.Configuration.GetValue<bool>("AdminMigration:NativeAccountBatchesEnabled"),
    builder.Configuration.GetValue<bool>("AdminMigration:NativeConfigurationEnabled"),
    builder.Configuration.GetValue<bool>("AdminMigration:NativeNoticeManagementEnabled"),
    builder.Configuration.GetValue<bool>("AdminMigration:NativeCentersEnabled"),
    builder.Configuration.GetValue<bool>("AdminMigration:NativeOperationalReadsEnabled"),
    builder.Configuration.GetValue<bool>("AdminMigration:NativeCandidateManagementEnabled"),
    builder.Configuration.GetValue<bool>("AdminMigration:NativeRegistrationPaymentWritesEnabled"),
    builder.Configuration.GetValue<bool>("AdminMigration:NativeWorkflowOperationsEnabled"),
    builder.Configuration.GetValue<bool>("AdminMigration:NativeExamManagementEnabled"),
    builder.Configuration.GetValue<bool>("AdminMigration:NativeArrangementsEnabled"),
    builder.Configuration.GetValue<bool>("AdminMigration:NativeResultsEnabled"),
    builder.Configuration.GetValue<bool>("AdminMigration:NativeAdmissionsEnabled"));
builder.Services.AddEisInfrastructure(
    DatabaseOptions.FromEnvironment(applicationRoot, builder.Environment.IsProduction()),
    DocumentVerificationOptions.FromEnvironment(builder.Environment.IsProduction()),
    authenticationOptions,
    candidateMigrationOptions,
    adminMigrationOptions);

var app = builder.Build();
await app.Services.InitializeEisDatabaseAsync();
app.Services.EnsureNativeAuthenticationReady(authenticationOptions);

app.UseExceptionHandler();
app.Use(async (context, next) =>
{
    context.Response.Headers.XContentTypeOptions = "nosniff";
    context.Response.Headers.XFrameOptions = "DENY";
    context.Response.Headers["Referrer-Policy"] = "same-origin";
    await next();
});

app.MapGet("/health/live", () => Results.Json(new
{
    status = "healthy",
    service = "Eis.Web",
    framework = ".NET 10"
}));

app.MapGet("/health/migration", (IApplicationCache cache) =>
{
    return Results.Json(new
    {
        status = "healthy",
        legacyApiAvailable = false,
        legacyApiRemoved = true,
        cache = new
        {
            status = cache.Status,
            redisEnabled = cache.Enabled,
            localFallback = true,
            namespaces = new[] { "public", "results" }
        },
        authentication = new
        {
            nativeEnabled = authenticationOptions.NativeEnabled,
            stateBackend = authenticationOptions.UsesRedis ? "redis" : "memory",
            sharesLegacySessions = authenticationOptions.SharesLegacySessions
        },
        candidate = new
        {
            nativeEnabled = candidateMigrationOptions.NativeEnabled,
            nativeRoutes = candidateMigrationOptions.NativeEnabled
                ? new[]
                {
                    "GET dashboard", "GET notices", "GET/PUT profile", "GET exams", "GET/POST registrations",
                    "GET results", "POST result appeals", "GET admit cards", "GET admissions", "PUT admission preferences"
                }
                : []
        },
        administration = new
        {
            nativeReadsEnabled = adminMigrationOptions.NativeReadsEnabled,
            nativeOrganizationWritesEnabled = adminMigrationOptions.NativeOrganizationWritesEnabled,
            nativeAccountBatchesEnabled = adminMigrationOptions.NativeAccountBatchesEnabled,
            nativeConfigurationEnabled = adminMigrationOptions.NativeConfigurationEnabled,
            nativeNoticeManagementEnabled = adminMigrationOptions.NativeNoticeManagementEnabled,
            nativeCentersEnabled = adminMigrationOptions.NativeCentersEnabled,
            nativeOperationalReadsEnabled = adminMigrationOptions.NativeOperationalReadsEnabled,
            nativeCandidateManagementEnabled = adminMigrationOptions.NativeCandidateManagementEnabled,
            nativeRegistrationPaymentWritesEnabled = adminMigrationOptions.NativeRegistrationPaymentWritesEnabled,
            nativeWorkflowOperationsEnabled = adminMigrationOptions.NativeWorkflowOperationsEnabled,
            nativeExamManagementEnabled = adminMigrationOptions.NativeExamManagementEnabled,
            nativeArrangementsEnabled = adminMigrationOptions.NativeArrangementsEnabled,
            nativeResultsEnabled = adminMigrationOptions.NativeResultsEnabled,
            nativeAdmissionsEnabled = adminMigrationOptions.NativeAdmissionsEnabled,
            nativeRoutes = (adminMigrationOptions.NativeReadsEnabled
                    ? new[] { "GET context", "GET dashboard", "GET schools", "GET school-organization", "GET admins", "GET exams" }
                    : [])
                .Concat(adminMigrationOptions.NativeOrganizationWritesEnabled
                    ? new[]
                    {
                        "POST/PATCH schools", "POST/PATCH classes", "POST/PATCH admins",
                        "POST admin password reset", "PUT self-registration setting"
                    }
                    : [])
                .Concat(adminMigrationOptions.NativeAccountBatchesEnabled
                    ? new[] { "GET/POST/PATCH candidate-account-batches" }
                    : [])
                .Concat(adminMigrationOptions.NativeConfigurationEnabled
                    ? new[] { "GET/POST number-rules", "GET/PUT workflows" }
                    : [])
                .Concat(adminMigrationOptions.NativeNoticeManagementEnabled
                    ? new[] { "GET/POST/PATCH notices", "PATCH system publications" }
                    : [])
                .Concat(adminMigrationOptions.NativeCentersEnabled
                    ? new[] { "GET/POST/PATCH centers", "PATCH center-change-requests" }
                    : [])
                .Concat(adminMigrationOptions.NativeOperationalReadsEnabled
                    ? new[] { "GET candidates", "GET registrations", "GET payments" }
                    : [])
                .Concat(adminMigrationOptions.NativeCandidateManagementEnabled
                    ? new[] { "POST candidate-accounts/archive", "POST candidate reset-password", "PATCH candidates" }
                    : [])
                .Concat(adminMigrationOptions.NativeRegistrationPaymentWritesEnabled
                    ? new[] { "PATCH registrations", "PATCH payments" }
                    : [])
                .Concat(adminMigrationOptions.NativeWorkflowOperationsEnabled
                    ? new[] { "GET workflow-instances", "PATCH workflow transfer/supervise" }
                    : [])
                .Concat(adminMigrationOptions.NativeExamManagementEnabled
                    ? new[] { "POST/PATCH exams", "POST exam archive" }
                    : [])
                .Concat(adminMigrationOptions.NativeArrangementsEnabled
                    ? new[]
                    {
                        "GET admission-arrangements", "POST arrangement preview/apply",
                        "GET admission exports"
                    }
                    : [])
                .Concat(adminMigrationOptions.NativeResultsEnabled
                    ? new[]
                    {
                        "GET/POST results", "POST result bulk", "POST/PATCH feature scores",
                        "PATCH score appeals", "GET result Excel export"
                    }
                    : [])
                .Concat(adminMigrationOptions.NativeAdmissionsEnabled
                    ? new[]
                    {
                        "GET admissions/indicator qualifications", "PUT qualification single/bulk",
                        "POST/PATCH/reset admission-school accounts", "PUT admission settings",
                        "POST/PATCH admission plans", "POST admission match/finalize/supplementary",
                        "PATCH admission reporting/withdrawals",
                        "GET/POST admin Excel", "GET/PUT admission notice template",
                        "GET/POST admission reporting Excel", "GET admission placement Excel"
                    }
                    : [])
                .ToArray()
        },
        features = MigrationFeatureCatalog.Current(authenticationOptions.NativeEnabled, candidateMigrationOptions.NativeEnabled)
    }, statusCode: StatusCodes.Status200OK);
});

app.MapNativePublicEndpoints();
app.MapNativeAuthenticationEndpoints(authenticationOptions);
app.MapNativeCandidateEndpoints(candidateMigrationOptions);
app.MapNativeAdminReadEndpoints(adminMigrationOptions);

string[] methods =
[
    HttpMethods.Get,
    HttpMethods.Head,
    HttpMethods.Post,
    HttpMethods.Put,
    HttpMethods.Patch,
    HttpMethods.Delete,
    HttpMethods.Options
];
app.MapMethods("/api/{**path}", methods, (HttpContext context) =>
{
    context.Response.Headers.CacheControl = "no-store";
    context.Response.Headers["X-EIS-Implementation"] = "aspnet-core";
    return Results.Json(
        new { ok = false, message = "API 接口不存在" },
        statusCode: StatusCodes.Status404NotFound);
});

app.MapFrontendAssets();

app.Run();

public partial class Program;
