using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using ZB.MOM.WW.MxGateway.Server;
using ZB.MOM.WW.MxGateway.Server.Dashboard;

namespace ZB.MOM.WW.MxGateway.Tests.Gateway.Dashboard;

public sealed class DashboardDisableLoginTests
{
    /// <summary>Verifies that when dashboard login is not disabled, the dashboard authentication scheme resolves to the cookie authentication handler.</summary>
    /// <returns>A task that represents the asynchronous operation.</returns>
    [Fact]
    public async Task DisableLoginOff_CookieSchemeUsesCookieHandler()
    {
        await using WebApplication app = GatewayApplication.Build([]);
        IAuthenticationSchemeProvider provider =
            app.Services.GetRequiredService<IAuthenticationSchemeProvider>();

        AuthenticationScheme? scheme = await provider.GetSchemeAsync(
            DashboardAuthenticationDefaults.AuthenticationScheme);

        Assert.NotNull(scheme);
        Assert.Equal(typeof(CookieAuthenticationHandler), scheme!.HandlerType);
    }

    /// <summary>Verifies that when <c>MxGateway:Dashboard:DisableLogin</c> is enabled, the dashboard authentication scheme resolves to the auto-login handler instead of the cookie handler.</summary>
    /// <returns>A task that represents the asynchronous operation.</returns>
    [Fact]
    public async Task DisableLoginOn_CookieSchemeUsesAutoLoginHandler()
    {
        await using WebApplication app = GatewayApplication.Build(
            ["--MxGateway:Dashboard:DisableLogin=true"]);
        IAuthenticationSchemeProvider provider =
            app.Services.GetRequiredService<IAuthenticationSchemeProvider>();

        AuthenticationScheme? scheme = await provider.GetSchemeAsync(
            DashboardAuthenticationDefaults.AuthenticationScheme);

        Assert.NotNull(scheme);
        Assert.Equal(typeof(DashboardAutoLoginAuthenticationHandler), scheme!.HandlerType);
    }

    /// <summary>Verifies that the auto-login principal created when login is disabled satisfies the Admin, Viewer, and hub-clients authorization policies.</summary>
    /// <returns>A task that represents the asynchronous operation.</returns>
    [Fact]
    public async Task DisableLoginOn_AutoLoginPrincipalSatisfiesAdminAndViewerPolicies()
    {
        await using WebApplication app = GatewayApplication.Build(
            ["--MxGateway:Dashboard:DisableLogin=true"]);
        IAuthorizationService authorization =
            app.Services.GetRequiredService<IAuthorizationService>();
        ClaimsPrincipal user = DashboardAutoLoginAuthenticationHandler.CreatePrincipal("multi-role");

        Assert.True((await authorization.AuthorizeAsync(
            user, resource: null, DashboardAuthenticationDefaults.AdminPolicy)).Succeeded);
        Assert.True((await authorization.AuthorizeAsync(
            user, resource: null, DashboardAuthenticationDefaults.ViewerPolicy)).Succeeded);
        Assert.True((await authorization.AuthorizeAsync(
            user, resource: null, DashboardAuthenticationDefaults.HubClientsPolicy)).Succeeded);
    }
}
