using NATS.Server.Auth;

namespace NATS.Server.Auth.Tests;

public class ClientPermissionsTests
{
    [Fact]
    public void No_permissions_allows_everything()
    {
        var perms = ClientPermissions.Build(null);
        perms.ShouldBeNull();
    }

    [Fact]
    public void Publish_allow_list_only()
    {
        var perms = ClientPermissions.Build(new Permissions
        {
            Publish = new SubjectPermission { Allow = ["foo.>", "bar.*"] },
        });

        perms.ShouldNotBeNull();
        perms.IsPublishAllowed("foo.bar").ShouldBeTrue();
        perms.IsPublishAllowed("foo.bar.baz").ShouldBeTrue();
        perms.IsPublishAllowed("bar.one").ShouldBeTrue();
        perms.IsPublishAllowed("baz.one").ShouldBeFalse();
    }

    [Fact]
    public void Publish_deny_list_only()
    {
        var perms = ClientPermissions.Build(new Permissions
        {
            Publish = new SubjectPermission { Deny = ["secret.>"] },
        });

        perms.ShouldNotBeNull();
        perms.IsPublishAllowed("foo.bar").ShouldBeTrue();
        perms.IsPublishAllowed("secret.data").ShouldBeFalse();
        perms.IsPublishAllowed("secret.nested.deep").ShouldBeFalse();
    }

    [Fact]
    public void Publish_allow_and_deny()
    {
        var perms = ClientPermissions.Build(new Permissions
        {
            Publish = new SubjectPermission
            {
                Allow = ["events.>"],
                Deny = ["events.internal.>"],
            },
        });

        perms.ShouldNotBeNull();
        perms.IsPublishAllowed("events.public.data").ShouldBeTrue();
        perms.IsPublishAllowed("events.internal.secret").ShouldBeFalse();
    }

    [Fact]
    public void Subscribe_allow_list()
    {
        var perms = ClientPermissions.Build(new Permissions
        {
            Subscribe = new SubjectPermission { Allow = ["data.>"] },
        });

        perms.ShouldNotBeNull();
        perms.IsSubscribeAllowed("data.updates").ShouldBeTrue();
        perms.IsSubscribeAllowed("admin.logs").ShouldBeFalse();
    }

    [Fact]
    public void Subscribe_deny_list()
    {
        var perms = ClientPermissions.Build(new Permissions
        {
            Subscribe = new SubjectPermission { Deny = ["admin.>"] },
        });

        perms.ShouldNotBeNull();
        perms.IsSubscribeAllowed("data.updates").ShouldBeTrue();
        perms.IsSubscribeAllowed("admin.logs").ShouldBeFalse();
    }

    [Fact]
    public void Publish_cache_returns_same_result()
    {
        var perms = ClientPermissions.Build(new Permissions
        {
            Publish = new SubjectPermission { Allow = ["foo.>"] },
        });

        perms.ShouldNotBeNull();
        perms.IsPublishAllowed("foo.bar").ShouldBeTrue();
        perms.IsPublishAllowed("foo.bar").ShouldBeTrue();
        perms.IsPublishAllowed("baz.bar").ShouldBeFalse();
        perms.IsPublishAllowed("baz.bar").ShouldBeFalse();
    }

    [Fact]
    public void Empty_permissions_object_allows_everything()
    {
        var perms = ClientPermissions.Build(new Permissions());
        perms.ShouldBeNull();
    }
}
