using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.DependencyInjection;
using ZB.MOM.WW.ScadaBridge.Security;
using ZB.MOM.WW.ScadaBridge.Security.Auth;
using Xunit;

namespace ZB.MOM.WW.ScadaBridge.Security.Tests;

public class DisableLoginRegistrationTests
{
    private static async Task<AuthenticationScheme?> ResolveCookieSchemeAsync(bool disableLogin)
    {
        var services = new ServiceCollection();
        services.AddLogging();
        services.AddSecurity(disableLogin);
        await using var sp = services.BuildServiceProvider();
        var provider = sp.GetRequiredService<IAuthenticationSchemeProvider>();
        return await provider.GetSchemeAsync(CookieAuthenticationDefaults.AuthenticationScheme);
    }

    [Fact]
    public async Task FlagTrue_RegistersAutoLoginHandlerUnderCookieScheme()
    {
        var scheme = await ResolveCookieSchemeAsync(disableLogin: true);
        Assert.Equal(typeof(AutoLoginAuthenticationHandler), scheme!.HandlerType);
    }

    [Fact]
    public async Task FlagFalse_RegistersCookieHandler()
    {
        var scheme = await ResolveCookieSchemeAsync(disableLogin: false);
        Assert.Equal(typeof(CookieAuthenticationHandler), scheme!.HandlerType);
    }

    /// <summary>
    /// When <c>disableLogin: false</c> (the production path) the M2.19 idle-timeout /
    /// role-refresh hook MUST be wired on the cookie scheme's
    /// <see cref="Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationEvents.OnValidatePrincipal"/>.
    /// This pin-test ensures a future refactor cannot silently drop the hook without
    /// a red test.
    /// </summary>
    [Fact]
    public async Task FlagFalse_CookieScheme_OnValidatePrincipalIsWired()
    {
        var services = new ServiceCollection();
        services.AddLogging();
        // Provide default SecurityOptions so the PostConfigure that reads
        // IOptions<SecurityOptions> (cookie-hardening + name) can resolve successfully.
        services.Configure<SecurityOptions>(_ => { });
        services.AddSecurity(disableLogin: false);

        await using var sp = services.BuildServiceProvider();

        var options = sp
            .GetRequiredService<Microsoft.Extensions.Options.IOptionsMonitor<CookieAuthenticationOptions>>()
            .Get(CookieAuthenticationDefaults.AuthenticationScheme);

        Assert.NotNull(options.Events?.OnValidatePrincipal);
    }
}
