using System.Net;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.HttpOverrides;
using RegistroPersonalAN.Components;
using RegistroPersonalAN.Models;
using RegistroPersonalAN.Services;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

builder.Services.AddHttpClient("DefaultClient", client =>
{
    client.BaseAddress = new Uri(Utilidades.urlSwagger());
});

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
    options.LoginPath = "/home";
    options.AccessDeniedPath = "/AccessDenied";
});

builder.Services.AddServerSideBlazor().AddCircuitOptions(option => { option.DetailedErrors = true; });
builder.Services.AddHttpContextAccessor();
builder.Services.AddDistributedMemoryCache();
builder.Services.Configure<CertificateLoginOptions>(builder.Configuration.GetSection("CertificateLogin"));
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedHost | ForwardedHeaders.XForwardedProto;
    options.ForwardLimit = null;
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();

    var knownProxies = builder.Configuration.GetSection("ReverseProxy:KnownProxies").Get<string[]>() ?? Array.Empty<string>();
    foreach (var knownProxy in knownProxies)
    {
        if (IPAddress.TryParse(knownProxy, out var proxyIp))
        {
            options.KnownProxies.Add(proxyIp);
        }
    }
});

builder.Services.AddSession(options =>
{
    options.IdleTimeout = TimeSpan.FromHours(1);
    options.Cookie.HttpOnly = true;
    options.Cookie.IsEssential = true;
});

builder.Services.AddHttpClient("CertClient").ConfigurePrimaryHttpMessageHandler(() =>
{
    return new HttpClientHandler
    {
        ClientCertificateOptions = ClientCertificateOption.Manual
    };
});

builder.Services.AddBlazorBootstrap();
builder.Services.AddAntiforgery();
builder.Services.AddSingleton<UserStateCookieStore>();
builder.Services.AddScoped<CertificateLoginBridgeService>();
builder.Services.AddScoped<UserState>();

var app = builder.Build();

app.UseForwardedHeaders();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSession();
app.UseRouting();

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

app.UseAntiforgery();

app.MapPost("/auth/state", (HttpContext context, UserStateCookiePayload payload, UserStateCookieStore cookieStore) =>
{
    cookieStore.Write(context, payload);
    return Results.Ok();
}).DisableAntiforgery();

app.MapDelete("/auth/state", (HttpContext context, UserStateCookieStore cookieStore) =>
{
    cookieStore.Clear(context);
    return Results.NoContent();
}).DisableAntiforgery();

app.MapGet("/auth/login-cert-bridge", (HttpContext context, CertificateLoginBridgeService bridgeService) =>
    bridgeService.HandleAsync(context));

app.Use(async (context, next) =>
{
    var userState = context.RequestServices.GetService<UserState>();
    var path = context.Request.Path;

    if (path == "/" ||
        path.StartsWithSegments("/auth/state") ||
        path.StartsWithSegments("/auth/login-cert-bridge") ||
        path.StartsWithSegments("/_blazor") ||
        path.StartsWithSegments("/Content") ||
        path.StartsWithSegments("/Scripts") ||
        path.StartsWithSegments("/js") ||
        path.StartsWithSegments("/favicon.ico") ||
        path.StartsWithSegments("/_framework"))
    {
        await next();
        return;
    }

    if (string.IsNullOrWhiteSpace(userState?.Token))
    {
        Console.WriteLine($"Redirigiendo al home desde: {path}");
        context.Response.Redirect("/");
        return;
    }

    await next();
});

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.Run();
