using Akka.Cluster;
using Shouldly;
using Xunit;

namespace ZB.MOM.WW.OtOpcUa.Host.IntegrationTests;

/// <summary>
/// Smoke test: verifies <see cref="TwoNodeClusterHarness"/> boots two nodes and they form
/// a 2-member cluster with the expected role topology. Failover + deploy scenarios layer
/// on top in Task 59.
/// </summary>
public sealed class ClusterFormationTests
{
    /// <summary>Verifies that two nodes form a 2-member cluster.</summary>
    [Fact]
    public async Task Two_nodes_form_a_2_member_cluster()
    {
        await using var harness = await TwoNodeClusterHarness.StartAsync();

        var aCluster = Akka.Cluster.Cluster.Get(harness.NodeASystem);
        var bCluster = Akka.Cluster.Cluster.Get(harness.NodeBSystem);

        aCluster.State.Members.Count(m => m.Status == MemberStatus.Up).ShouldBe(2);
        bCluster.State.Members.Count(m => m.Status == MemberStatus.Up).ShouldBe(2);

        var aRoles = aCluster.State.Members.SelectMany(m => m.Roles).Distinct().ToHashSet();
        aRoles.ShouldContain("admin");
        aRoles.ShouldContain("driver");
    }

    /// <summary>Verifies that both nodes see each other as role members.</summary>
    [Fact]
    public async Task Both_nodes_see_each_other_as_role_members()
    {
        await using var harness = await TwoNodeClusterHarness.StartAsync();

        var aCluster = Akka.Cluster.Cluster.Get(harness.NodeASystem);
        aCluster.State.Members
            .Where(m => m.Roles.Contains("driver") && m.Status == MemberStatus.Up)
            .Count().ShouldBe(2);
        aCluster.State.Members
            .Where(m => m.Roles.Contains("admin") && m.Status == MemberStatus.Up)
            .Count().ShouldBe(2);
    }
}
