using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using ZB.MOM.WW.MxGateway.Server;
using ZB.MOM.WW.MxGateway.Server.Dashboard;

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

public sealed class DashboardCookieOptionsTests
{
    /// <summary>Verifies that the application configures secure dashboard authentication cookies.</summary>
    [Fact]
    public async Task Build_ConfiguresSecureDashboardCookie()
    {
        await using WebApplication app = GatewayApplication.Build([]);
        IOptionsMonitor<CookieAuthenticationOptions> optionsMonitor = app.Services
            .GetRequiredService<IOptionsMonitor<CookieAuthenticationOptions>>();

        CookieAuthenticationOptions options = optionsMonitor.Get(
            DashboardAuthenticationDefaults.AuthenticationScheme);

        Assert.Equal(DashboardAuthenticationDefaults.CookieName, options.Cookie.Name);
        Assert.True(options.Cookie.HttpOnly);
        Assert.Equal(CookieSecurePolicy.Always, options.Cookie.SecurePolicy);
        Assert.Equal(SameSiteMode.Strict, options.Cookie.SameSite);
        Assert.Equal("/", options.Cookie.Path);
        Assert.Equal("/login", options.LoginPath);
        Assert.Equal("/logout", options.LogoutPath);
        Assert.Equal("/denied", options.AccessDeniedPath);
    }

    /// <summary>
    /// Verifies that setting <c>MxGateway:Dashboard:RequireHttpsCookie=false</c>
    /// relaxes the cookie to <see cref="CookieSecurePolicy.SameAsRequest"/> so
    /// the dashboard can be reached over plain HTTP in dev.
    /// </summary>
    [Fact]
    public async Task Build_WithRequireHttpsCookieFalse_UsesSameAsRequest()
    {
        await using WebApplication app = GatewayApplication.Build(
            ["--MxGateway:Dashboard:RequireHttpsCookie=false"]);
        IOptionsMonitor<CookieAuthenticationOptions> optionsMonitor = app.Services
            .GetRequiredService<IOptionsMonitor<CookieAuthenticationOptions>>();

        CookieAuthenticationOptions options = optionsMonitor.Get(
            DashboardAuthenticationDefaults.AuthenticationScheme);

        Assert.Equal(CookieSecurePolicy.SameAsRequest, options.Cookie.SecurePolicy);
    }

    /// <summary>
    /// Verifies that <c>MxGateway:Dashboard:CookieName</c> overrides the dashboard auth
    /// cookie name, so a gateway instance sharing a hostname with another can be given a
    /// distinct name (browser cookies are scoped by host+path, not port).
    /// </summary>
    [Fact]
    public async Task Build_WithCookieNameOverride_UsesConfiguredName()
    {
        await using WebApplication app = GatewayApplication.Build(
            ["--MxGateway:Dashboard:CookieName=MxGatewayDashboard.env2"]);
        IOptionsMonitor<CookieAuthenticationOptions> optionsMonitor = app.Services
            .GetRequiredService<IOptionsMonitor<CookieAuthenticationOptions>>();

        CookieAuthenticationOptions options = optionsMonitor.Get(
            DashboardAuthenticationDefaults.AuthenticationScheme);

        Assert.Equal("MxGatewayDashboard.env2", options.Cookie.Name);
    }
}
