using Shouldly;
using ZB.MOM.NatsNet.Server;

namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;

public sealed class JetStreamSuperClusterTests
{
    [Fact] // T:1453
    public void JetStreamSuperClusterMoveCancel_ShouldSucceed()
    {
        var updates = new RecoveryUpdates();
        var stream = new StreamAssignment { Client = new ClientInfo { Account = "ACC" }, Config = new StreamConfig { Name = "ORDERS" } };
        updates.AddStream(stream);
        updates.RemoveStream(stream);

        updates.AddStreams.ShouldBeEmpty();
        updates.RemoveStreams.ShouldContainKey("ACC:ORDERS");
    }

    [Fact] // T:1454
    public void JetStreamSuperClusterDoubleStreamMove_ShouldSucceed()
    {
        var cluster = new JetStreamCluster();
        var assignment = new StreamAssignment { Config = new StreamConfig { Name = "ORDERS" } };

        cluster.TrackInflightStreamProposal("ACC", assignment, deleted: false);
        cluster.TrackInflightStreamProposal("ACC", assignment, deleted: false);
        cluster.InflightStreams["ACC"]["ORDERS"].Ops.ShouldBe(2UL);
    }

    [Fact] // T:1457
    public void JetStreamSuperClusterSystemLimitsPlacement_ShouldSucceed()
    {
        var engine = new JetStreamEngine(new global::ZB.MOM.NatsNet.Server.JetStream());
        engine.IsClustered().ShouldBeFalse();
        engine.IsClusteredNoLock().ShouldBeFalse();
    }

    [Fact] // T:1465
    public void JetStreamSuperClusterConsumerAckSubjectWithStreamImportProtocolError_ShouldSucceed()
    {
        var updates = new RecoveryUpdates();
        var consumer = new ConsumerAssignment { Client = new ClientInfo { Account = "ACC" }, Stream = "ORDERS", Name = "ship" };

        updates.AddOrUpdateConsumer(consumer);
        updates.UpdateConsumers["ACC:ORDERS"].ShouldContainKey("ORDERS:ship");
    }

    [Fact] // T:1426
    public void JetStreamSuperClusterInterestOnlyMode_ShouldSucceed()
    {
        var outSide = new OutSide
        {
            Mode = GatewayInterestMode.Transitioning,
            Ni = new HashSet<string>(StringComparer.Ordinal) { "foo" },
        };

        outSide.AcquireWriteLock();
        try
        {
            outSide.Ni = null;
            outSide.Mode = GatewayInterestMode.InterestOnly;
        }
        finally
        {
            outSide.ReleaseWriteLock();
        }

        outSide.AcquireReadLock();
        try
        {
            outSide.Mode.ShouldBe(GatewayInterestMode.InterestOnly);
            outSide.Ni.ShouldBeNull();
        }
        finally
        {
            outSide.ReleaseReadLock();
        }
    }
}
