using NATS.E2E.Tests.Infrastructure;

namespace NATS.E2E.Tests;

[Collection("E2E-LeafNode")]
public class LeafNodeTests(LeafNodeFixture fixture)
{
    [Fact]
    public async Task LeafNode_HubToLeaf_MessageDelivered()
    {
        await using var pub = fixture.CreateHubClient();
        await using var sub = fixture.CreateLeafClient();
        await pub.ConnectAsync();
        await sub.ConnectAsync();

        await using var subscription = await sub.SubscribeCoreAsync<string>("e2e.leaf.h2l");
        // Ping both sides: subscriber's ping flushes the SUB to the leaf server,
        // publisher's ping ensures the hub has received the propagated interest.
        await sub.PingAsync();
        await pub.PingAsync();

        await pub.PublishAsync("e2e.leaf.h2l", "hub-to-leaf");

        using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
        var msg = await subscription.Msgs.ReadAsync(cts.Token);
        msg.Data.ShouldBe("hub-to-leaf");
    }

    [Fact]
    public async Task LeafNode_LeafToHub_MessageDelivered()
    {
        await using var pub = fixture.CreateLeafClient();
        await using var sub = fixture.CreateHubClient();
        await pub.ConnectAsync();
        await sub.ConnectAsync();

        await using var subscription = await sub.SubscribeCoreAsync<string>("e2e.leaf.l2h");
        // Ping both sides: subscriber's ping flushes the SUB to the hub server,
        // publisher's ping ensures the leaf has received the propagated interest.
        await sub.PingAsync();
        await pub.PingAsync();

        await pub.PublishAsync("e2e.leaf.l2h", "leaf-to-hub");

        using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
        var msg = await subscription.Msgs.ReadAsync(cts.Token);
        msg.Data.ShouldBe("leaf-to-hub");
    }

    [Fact]
    public async Task LeafNode_OnlySubscribedSubjectsPropagate()
    {
        await using var pub = fixture.CreateHubClient();
        await using var sub = fixture.CreateLeafClient();
        await pub.ConnectAsync();
        await sub.ConnectAsync();

        await using var subscription = await sub.SubscribeCoreAsync<string>("e2e.leaf.specific");
        // Ping both sides to ensure subscription interest has propagated before publishing.
        await sub.PingAsync();
        await pub.PingAsync();

        await pub.PublishAsync("e2e.leaf.other", "wrong-subject");
        await pub.PublishAsync("e2e.leaf.specific", "right-subject");

        using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
        var msg = await subscription.Msgs.ReadAsync(cts.Token);
        msg.Data.ShouldBe("right-subject");
    }
}
