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

namespace NATS.Server.JetStream.Tests.JetStream;

public class JetStreamRetentionRuntimeStrictParityTests
{
    [Fact]
    public async Task Limits_interest_and_workqueue_retention_diverge_by_runtime_contract()
    {
        var consumers = new ConsumerManager();
        var streams = new StreamManager(consumerManager: consumers);

        streams.CreateOrUpdate(new StreamConfig
        {
            Name = "WQ_STRICT",
            Subjects = ["wq.strict"],
            Retention = RetentionPolicy.WorkQueue,
            MaxMsgs = 32,
        }).Error.ShouldBeNull();
        streams.CreateOrUpdate(new StreamConfig
        {
            Name = "INT_STRICT",
            Subjects = ["int.strict"],
            Retention = RetentionPolicy.Interest,
            MaxMsgs = 32,
        }).Error.ShouldBeNull();

        consumers.CreateOrUpdate("WQ_STRICT", new ConsumerConfig { DurableName = "WQ", AckPolicy = AckPolicy.All }).Error.ShouldBeNull();
        consumers.CreateOrUpdate("INT_STRICT", new ConsumerConfig { DurableName = "INT", AckPolicy = AckPolicy.All }).Error.ShouldBeNull();

        streams.Capture("wq.strict", "one"u8.ToArray());
        streams.Capture("wq.strict", "two"u8.ToArray());
        streams.Capture("int.strict", "one"u8.ToArray());
        streams.Capture("int.strict", "two"u8.ToArray());

        consumers.AckAll("WQ_STRICT", "WQ", 1).ShouldBeTrue();
        consumers.AckAll("INT_STRICT", "INT", 1).ShouldBeTrue();

        // Trigger another retention pass after ack-floor updates.
        streams.Capture("wq.strict", "three"u8.ToArray());
        streams.Capture("int.strict", "three"u8.ToArray());

        streams.TryGet("WQ_STRICT", out var wq).ShouldBeTrue();
        streams.TryGet("INT_STRICT", out var interest).ShouldBeTrue();

        var wqState = await wq.Store.GetStateAsync(default);
        var interestState = await interest.Store.GetStateAsync(default);

        wqState.Messages.ShouldBe((ulong)2);       // seq=1 pruned by workqueue ack floor
        interestState.Messages.ShouldBe((ulong)3); // interest retention does not use ack-floor pruning
    }
}
