using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Configuration.Enums;

namespace ZB.MOM.WW.OtOpcUa.Configuration.Tests;

/// <summary>
///     Pins the underlying type of <see cref="NodePermissions"/> to <c>int</c> so the SQL
///     storage type (<c>HasConversion&lt;int&gt;()</c> in <c>OtOpcUaConfigDbContext</c>) and the
///     XML doc ("Stored as int") cannot drift back into the latent <c>uint→int</c> overflow
///     trap caught by Configuration-004.
/// </summary>
[Trait("Category", "Unit")]
public sealed class NodePermissionsTests
{
    /// <summary>Verifies that the underlying type is int so it matches HasConversion in DbContext.</summary>
    [Fact]
    public void Underlying_type_is_int_so_it_matches_HasConversion_in_DbContext()
    {
        // Configuration-004: NodePermissions was declared : uint while NodeAcl.PermissionFlags
        // is persisted via HasConversion<int>(). A bit-31 grant would overflow int and corrupt
        // the round-trip. Lock the underlying type to int.
        typeof(NodePermissions).GetEnumUnderlyingType().ShouldBe(typeof(int));
    }

    /// <summary>Verifies that all defined bits round trip through int cast without loss.</summary>
    [Fact]
    public void All_defined_bits_round_trip_through_int_cast_without_loss()
    {
        // Belt-and-braces: every declared bit must survive a (int) round-trip — fails today
        // if anyone re-introduces a bit-31 flag while the underlying type is uint.
        foreach (NodePermissions value in Enum.GetValues<NodePermissions>())
        {
            var asInt = (int)value;
            var roundTripped = (NodePermissions)asInt;
            roundTripped.ShouldBe(value);
        }
    }

    /// <summary>Verifies that bitwise combinations round trip through int storage.</summary>
    [Fact]
    public void Bitwise_combinations_round_trip_through_int_storage()
    {
        // The PermissionFlags column stores int; combinations of bits must survive the conversion.
        var combo = NodePermissions.Engineer | NodePermissions.MethodCall;
        var stored = (int)combo;
        var rebuilt = (NodePermissions)stored;
        rebuilt.ShouldBe(combo);
        rebuilt.HasFlag(NodePermissions.WriteTune).ShouldBeTrue();
        rebuilt.HasFlag(NodePermissions.MethodCall).ShouldBeTrue();
    }
}
