using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Commons.Messages.Redundancy;
using ZB.MOM.WW.OtOpcUa.Runtime.Drivers;

namespace ZB.MOM.WW.OtOpcUa.Runtime.Tests.Drivers;

/// <summary>
///     archreview 03/S4 — the single Primary data-plane gate decision. A KNOWN role wins outright; an
///     UNKNOWN role (no snapshot yet, or the snapshot never mentioned this node) is resolved by cluster
///     membership: a single-driver cluster stays default-ALLOW (boot-window / single-node posture), a
///     multi-driver cluster is default-DENY (a real Primary peer exists — don't touch the shared field
///     device until the snapshot proves this node is Primary).
/// </summary>
public sealed class PrimaryGatePolicyTests
{
    [Theory]
    // Primary → always service, regardless of member count.
    [InlineData(RedundancyRole.Primary, 0, true)]
    [InlineData(RedundancyRole.Primary, 1, true)]
    [InlineData(RedundancyRole.Primary, 2, true)]
    // Secondary / Detached → never service, regardless of member count.
    [InlineData(RedundancyRole.Secondary, 0, false)]
    [InlineData(RedundancyRole.Secondary, 2, false)]
    [InlineData(RedundancyRole.Detached, 0, false)]
    [InlineData(RedundancyRole.Detached, 2, false)]
    public void Known_role_wins_regardless_of_member_count(RedundancyRole role, int members, bool expected)
        => PrimaryGatePolicy.ShouldServiceAsPrimary(role, members).ShouldBe(expected);

    [Theory]
    // Unknown role: allow only when no driver peer exists (count <= 1).
    [InlineData(0, true)]
    [InlineData(1, true)]
    [InlineData(2, false)]
    [InlineData(3, false)]
    public void Unknown_role_resolves_by_membership(int members, bool expected)
        => PrimaryGatePolicy.ShouldServiceAsPrimary(null, members).ShouldBe(expected);
}
