using NATS.Server.JetStream;
using NATS.Server.JetStream.Models;

namespace NATS.Server.JetStream.Tests.JetStream;

public class JetStreamConsumerStateMachineStrictParityTests
{
    [Fact]
    public async Task Ack_redelivery_backoff_and_replay_timing_follow_monotonic_consumer_state_machine_rules()
    {
        var streams = new StreamManager();
        var consumers = new ConsumerManager();

        streams.CreateOrUpdate(new StreamConfig
        {
            Name = "ORDERS_SM",
            Subjects = ["orders.sm"],
            Retention = RetentionPolicy.Limits,
            MaxMsgs = 32,
        }).Error.ShouldBeNull();

        consumers.CreateOrUpdate("ORDERS_SM", new ConsumerConfig
        {
            DurableName = "D1",
            AckPolicy = AckPolicy.Explicit,
            AckWaitMs = 1,
            MaxDeliver = 1,
            BackOffMs = [1],
        }).Error.ShouldBeNull();

        streams.Capture("orders.sm", "x"u8.ToArray());

        var first = await consumers.FetchAsync("ORDERS_SM", "D1", 1, streams, default);
        first.Messages.Count.ShouldBe(1);

        await Task.Delay(5);
        var second = await consumers.FetchAsync("ORDERS_SM", "D1", 1, streams, default);
        second.Messages.Count.ShouldBe(1);
        second.Messages[0].Redelivered.ShouldBeTrue();

        await Task.Delay(5);
        var third = await consumers.FetchAsync("ORDERS_SM", "D1", 1, streams, default);

        // MaxDeliver=1 allows one redelivery, then the sequence is retired.
        third.Messages.Count.ShouldBe(0);
    }
}
