using Hangfire;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Serilog;
using TrueCV.Infrastructure;
using TrueCV.Infrastructure.Data;
using TrueCV.Infrastructure.Identity;
using TrueCV.Web;
using TrueCV.Web.Components;

// Configure Serilog
Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .CreateBootstrapLogger();

try
{
    Log.Information("Starting TrueCV web application");

    var builder = WebApplication.CreateBuilder(args);

    // Configure Serilog from appsettings
    builder.Host.UseSerilog((context, services, configuration) => configuration
        .ReadFrom.Configuration(context.Configuration)
        .ReadFrom.Services(services)
        .Enrich.FromLogContext());

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

    // Add Infrastructure services (DbContext, Hangfire, HttpClients, Services)
    builder.Services.AddInfrastructure(builder.Configuration);

    // Add Identity with secure password requirements
    builder.Services.AddIdentity<ApplicationUser, IdentityRole<Guid>>(options =>
    {
        options.Password.RequireDigit = true;
        options.Password.RequireLowercase = true;
        options.Password.RequireUppercase = true;
        options.Password.RequireNonAlphanumeric = true;
        options.Password.RequiredLength = 12;
        options.Password.RequiredUniqueChars = 4;
        options.SignIn.RequireConfirmedAccount = false;
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
        options.Lockout.MaxFailedAccessAttempts = 5;
        options.Lockout.AllowedForNewUsers = true;
    })
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

    builder.Services.ConfigureApplicationCookie(options =>
    {
        options.LoginPath = "/account/login";
        options.LogoutPath = "/account/logout";
        options.AccessDeniedPath = "/account/login";
    });

    // Add Cascading Authentication State
    builder.Services.AddCascadingAuthenticationState();
    builder.Services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<ApplicationUser>>();

    // Add health checks
    builder.Services.AddHealthChecks()
        .AddDbContextCheck<ApplicationDbContext>("database");

    var app = builder.Build();

    // Seed default admin user
    using (var scope = app.Services.CreateScope())
    {
        var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
        var defaultEmail = "admin@truecv.local";
        var defaultPassword = "TrueCV_Admin123!";

        if (await userManager.FindByEmailAsync(defaultEmail) == null)
        {
            var adminUser = new ApplicationUser
            {
                UserName = defaultEmail,
                Email = defaultEmail,
                EmailConfirmed = true
            };
            await userManager.CreateAsync(adminUser, defaultPassword);
            Log.Information("Created default admin user: {Email}", defaultEmail);
        }
    }

    // Configure the HTTP request pipeline.
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Error", createScopeForErrors: true);
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }

    // Only use HTTPS redirection when not running in Docker/container
    if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER")))
    {
        // Running in container - skip HTTPS redirect (handled by reverse proxy)
    }
    else
    {
        app.UseHttpsRedirection();
    }

    app.UseStaticFiles();
    app.UseAntiforgery();

    // Add Serilog request logging
    app.UseSerilogRequestLogging();

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

    // Add Hangfire Dashboard (only in development)
    if (app.Environment.IsDevelopment())
    {
        app.UseHangfireDashboard("/hangfire", new DashboardOptions
        {
            Authorization = [] // Allow anonymous access in development
        });
    }

    // Login endpoint
    app.MapPost("/account/perform-login", async (
        HttpContext context,
        SignInManager<ApplicationUser> signInManager) =>
    {
        var form = await context.Request.ReadFormAsync();
        var email = form["email"].ToString();
        var password = form["password"].ToString();
        var rememberMe = form["rememberMe"].ToString() == "true";
        var returnUrl = form["returnUrl"].ToString();

        Log.Information("Login attempt for {Email}", email);

        // Validate returnUrl is local to prevent open redirect attacks
        if (string.IsNullOrEmpty(returnUrl) || !Uri.IsWellFormedUriString(returnUrl, UriKind.Relative) || returnUrl.StartsWith("//"))
        {
            returnUrl = "/dashboard";
        }

        var result = await signInManager.PasswordSignInAsync(email, password, rememberMe, lockoutOnFailure: true);

        if (result.Succeeded)
        {
            Log.Information("User {Email} logged in successfully", email);
            return Results.LocalRedirect(returnUrl);
        }
        else if (result.IsLockedOut)
        {
            Log.Warning("User {Email} account is locked out", email);
            return Results.Redirect("/account/login?error=Account+locked.+Try+again+later.");
        }
        else
        {
            Log.Warning("Failed login attempt for {Email}", email);
            return Results.Redirect("/account/login?error=Invalid+email+or+password.");
        }
    });

    // Logout endpoint
    app.MapPost("/account/logout", async (SignInManager<ApplicationUser> signInManager) =>
    {
        await signInManager.SignOutAsync();
        return Results.Redirect("/");
    }).RequireAuthorization();

    // Health check endpoint
    app.MapHealthChecks("/health");

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

    app.Run();
}
catch (Exception ex)
{
    Log.Fatal(ex, "Application terminated unexpectedly");
}
finally
{
    Log.CloseAndFlush();
}
