using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

namespace ScadaLink.Security;

public static class ServiceCollectionExtensions
{
    public static IServiceCollection AddSecurity(this IServiceCollection services)
    {
        services.AddScoped<LdapAuthService>();
        services.AddScoped<JwtTokenService>();
        services.AddScoped<RoleMapper>();

        // Register ASP.NET Core authentication with cookie scheme
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options =>
            {
                options.LoginPath = "/login";
                options.LogoutPath = "/auth/logout";
                options.Cookie.Name = "ScadaLink.Auth";
                options.Cookie.HttpOnly = true;
                options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict;
                // Cookie.SecurePolicy is set in the PostConfigure block below so it
                // can honour SecurityOptions.RequireHttpsCookie.
            });

        // CentralUI-005: configure the cookie session as a sliding window so the
        // code matches the documented policy ("sliding refresh, 30-minute idle
        // timeout"). ASP.NET cookie auth exposes a single ExpireTimeSpan plus a
        // SlidingExpiration flag — it cannot natively model a 15-minute sliding
        // token AND a separate 30-minute absolute idle cap. The faithful
        // interpretation: the cookie window IS the idle timeout
        // (SecurityOptions.IdleTimeoutMinutes, default 30) and SlidingExpiration
        // renews it on activity (the middleware re-issues the cookie once past
        // the halfway mark of the window). An active user is therefore kept
        // signed in; an idle user is signed out after the idle timeout. The
        // 15-minute JwtExpiryMinutes governs the lifetime of the embedded JWT
        // itself (see JwtTokenService) — a separate layer from the cookie
        // session window. Bound here via PostConfigure so SecurityOptions
        // (configured by the Host after AddSecurity) is honoured.
        services.AddOptions<CookieAuthenticationOptions>(CookieAuthenticationDefaults.AuthenticationScheme)
            .Configure<IOptions<SecurityOptions>>((cookieOptions, securityOptions) =>
            {
                var idleMinutes = securityOptions.Value.IdleTimeoutMinutes;
                cookieOptions.ExpireTimeSpan = TimeSpan.FromMinutes(idleMinutes);
                cookieOptions.SlidingExpiration = true;

                // The cookie carries the embedded JWT bearer credential. Production
                // keeps it HTTPS-only (Always); an HTTP-only deployment (e.g. the
                // local Docker dev cluster) opts out via RequireHttpsCookie=false and
                // uses SameAsRequest — still Secure on any HTTPS request.
                cookieOptions.Cookie.SecurePolicy = securityOptions.Value.RequireHttpsCookie
                    ? Microsoft.AspNetCore.Http.CookieSecurePolicy.Always
                    : Microsoft.AspNetCore.Http.CookieSecurePolicy.SameAsRequest;
            });

        services.AddScadaLinkAuthorization();

        return services;
    }

    public static IServiceCollection AddSecurityActors(this IServiceCollection services)
    {
        // Phase 0: placeholder for Akka actor registration
        return services;
    }
}
