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

namespace NATS.Server.Tests;

public class JetStreamRetentionRuntimeParityTests
{
    [Fact]
    public async Task Workqueue_and_interest_retention_apply_correct_eviction_rules_under_ack_and_interest_changes()
    {
        var invariantViolations = new List<string>();

        var invalidWorkQueue = JetStreamConfigValidator.Validate(new StreamConfig
        {
            Name = "WQ_INVALID",
            Subjects = ["wq.invalid"],
            Retention = RetentionPolicy.WorkQueue,
            MaxConsumers = 0,
        });
        if (invalidWorkQueue.IsValid)
            invariantViolations.Add("WorkQueue retention accepted MaxConsumers=0.");

        var manager = new StreamManager();
        manager.CreateOrUpdate(new StreamConfig
        {
            Name = "WQ",
            Subjects = ["wq.*"],
            Retention = RetentionPolicy.WorkQueue,
            MaxConsumers = 1,
            MaxMsgs = 1,
        }).Error.ShouldBeNull();

        manager.CreateOrUpdate(new StreamConfig
        {
            Name = "INT",
            Subjects = ["int.*"],
            Retention = RetentionPolicy.Interest,
            MaxMsgsPer = 1,
        }).Error.ShouldBeNull();

        manager.Capture("wq.a", "first"u8.ToArray());
        manager.Capture("wq.a", "second"u8.ToArray());
        manager.TryGet("WQ", out var wq).ShouldBeTrue();
        var wqState = await wq.Store.GetStateAsync(default);
        if (wqState.Messages != 1)
            invariantViolations.Add($"WorkQueue stream expected 1 message, found {wqState.Messages}.");

        manager.Capture("int.a", "one"u8.ToArray());
        manager.Capture("int.a", "two"u8.ToArray());
        manager.TryGet("INT", out var interest).ShouldBeTrue();
        var interestState = await interest.Store.GetStateAsync(default);
        if (interestState.Messages != 1)
            invariantViolations.Add($"Interest stream expected 1 message after per-subject pruning, found {interestState.Messages}.");

        invariantViolations.ShouldBeEmpty();
    }
}
