using DodoSSH.Domain.Authorization;

namespace DodoSSH.Domain.Tests.Authorization;

/// <summary>
/// Permission algebra. This grows into the full effective-permission suite in M3; for now
/// it pins the flag values, because they are persisted as an integer column and changing
/// one silently reinterprets every stored ACL row.
/// </summary>
public sealed class PermissionFlagsTests
{
    [Theory]
    [InlineData(PermissionFlags.None, 0)]
    [InlineData(PermissionFlags.Read, 1)]
    [InlineData(PermissionFlags.Write, 2)]
    [InlineData(PermissionFlags.Connect, 4)]
    [InlineData(PermissionFlags.Share, 8)]
    [InlineData(PermissionFlags.Admin, 16)]
    public void Flag_HasStableWireValue(PermissionFlags flag, int expected)
    {
        // These values are persisted; a change reinterprets existing ACL rows.
        ((int)flag).ShouldBe(expected);
    }

    [Fact]
    public void Union_CombinesGrantsFromMultipleSubjects()
    {
        // Effective permissions are a union across direct and team-derived grants.
        var direct = PermissionFlags.Read;
        var viaTeam = PermissionFlags.Write | PermissionFlags.Connect;

        var effective = direct | viaTeam;

        effective.HasFlag(PermissionFlags.Read).ShouldBeTrue();
        effective.HasFlag(PermissionFlags.Write).ShouldBeTrue();
        effective.HasFlag(PermissionFlags.Connect).ShouldBeTrue();
        effective.HasFlag(PermissionFlags.Admin).ShouldBeFalse();
        effective.HasFlag(PermissionFlags.Share).ShouldBeFalse();
    }

    [Fact]
    public void Union_IsMonotonic()
    {
        // The deliberate consequence of having no Deny rules: adding a grant can only
        // ever widen access, never narrow it. M3's evaluator relies on this.
        var before = PermissionFlags.Read;
        var after = before | PermissionFlags.Admin;

        (after & before).ShouldBe(before);
    }
}
