using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Negotiate;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using RIIT.Components;
using RIIT.Components.Account;
using RIIT.Data;

var builder = WebApplication.CreateBuilder(args);

// ===== Auth mode switches (configurable via appsettings.json) =====
var authMode = builder.Configuration["Auth:Mode"]?.Trim() ?? "Internal";
var windowsEnabled = string.Equals(authMode, "Windows", StringComparison.OrdinalIgnoreCase);

// Detect IIS / IIS Express hosting (intranet scenario)
var runningUnderIis = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ASPNETCORE_IIS_PHYSICAL_PATH"));

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

builder.Services.AddCascadingAuthenticationState();
builder.Services.AddScoped<IdentityRedirectManager>();
builder.Services.AddScoped<AuthenticationStateProvider, IdentityRevalidatingAuthenticationStateProvider>();

// Authentication: primary = Identity cookie
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = IdentityConstants.ApplicationScheme;
    options.DefaultSignInScheme = IdentityConstants.ExternalScheme;

    // Keep challenge on cookie/login page; Windows is performed explicitly via /auth/windows.
    options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
})
    .AddIdentityCookies();

// Windows Integrated (Kerberos/NTLM):
// - On IIS / IIS Express: do NOT register AddNegotiate(); IIS handles Windows auth and populates HttpContext.User.
// - Outside IIS: you may register AddNegotiate() (optional), but typical intranet hosting uses IIS anyway.
if (windowsEnabled && !runningUnderIis)
{
    builder.Services.AddAuthentication()
        .AddNegotiate();
}

builder.Services.AddAuthorization();

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
    ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");

builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));

builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddIdentityCore<ApplicationUser>(options =>
{
    // Email confirmation disabled for now (can be enabled later)
    options.SignIn.RequireConfirmedAccount = false;
    options.Stores.SchemaVersion = IdentitySchemaVersions.Version3;
})
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddSignInManager()
    .AddDefaultTokenProviders();

builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();

var app = builder.Build();

// Optionally guard against misconfiguration
// (Windows mode is intended for IIS/IIS Express intranet hosting)
if (windowsEnabled && !runningUnderIis)
{
    app.Logger.LogWarning("Auth:Mode=Windows but the app is not running under IIS/IIS Express. Windows Integrated auth may not work as expected.");
}

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    app.UseHsts();
}

app.UseStatusCodePagesWithReExecute("/not-found");
app.UseHttpsRedirection();

app.UseStaticFiles();
app.UseRouting();



app.UseAuthentication();

if (windowsEnabled)
{
    app.Use(async (context, next) =>
    {
        // Pokud už je přihlášený (cookie), nech vše projít.
        if (context.User?.Identity?.IsAuthenticated == true)
        {
            await next();
            return;
        }

        var path = context.Request.Path;

        // Nikdy neredirectovat:
        // - bootstrap endpoint
        // - identity stránky/endpoints
        // - chybové stránky
        // - blazor framework a static web assets
        if (path.StartsWithSegments("/auth/windows") ||
            path.StartsWithSegments("/Account") ||
            path.StartsWithSegments("/not-found") ||
            path.StartsWithSegments("/Error") ||
            path.StartsWithSegments("/_framework") ||
            path.StartsWithSegments("/_content"))
        {
            await next();
            return;
        }

        // Nezasahovat do statických souborů podle přípony (CSS/JS/fonts/images/maps)
        var ext = System.IO.Path.GetExtension(path);
        if (!string.IsNullOrEmpty(ext))
        {
            await next();
            return;
        }

        // Redirect jen pro "navigační" requesty (typicky HTML stránky)
        if (!HttpMethods.IsGet(context.Request.Method))
        {
            await next();
            return;
        }

        // Pokud klient nechce HTML (např. fetch pro JSON), neredirectuj
        var accept = context.Request.Headers.Accept.ToString();
        if (!string.IsNullOrEmpty(accept) && !accept.Contains("text/html", StringComparison.OrdinalIgnoreCase))
        {
            await next();
            return;
        }

        var returnUrl = context.Request.PathBase + context.Request.Path + context.Request.QueryString;
        var target = "/auth/windows?returnUrl=" + Uri.EscapeDataString(returnUrl);
        

        context.Response.Redirect(target);
    });
}

app.UseAuthorization();

app.UseAntiforgery();



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

// Add additional endpoints required by the Identity /Account Razor components.
app.MapAdditionalIdentityEndpoints();

app.Run();