using NATS.Client.Core;
using NATS.E2E.Tests.Infrastructure;

namespace NATS.E2E.Tests;

[Collection("E2E")]
public class HeaderTests(NatsServerFixture fixture)
{
    [Fact]
    public async Task Headers_PublishWithHeaders_ReceivedIntact()
    {
        await using var pub = fixture.CreateClient();
        await using var sub = fixture.CreateClient();
        await pub.ConnectAsync();
        await sub.ConnectAsync();

        await using var subscription = await sub.SubscribeCoreAsync<string>("e2e.hdr.basic");
        await sub.PingAsync();

        var headers = new NatsHeaders { { "X-Test-Key", "test-value" } };
        await pub.PublishAsync("e2e.hdr.basic", "with-headers", headers: headers);

        using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
        var msg = await subscription.Msgs.ReadAsync(cts.Token);

        msg.Data.ShouldBe("with-headers");
        msg.Headers.ShouldNotBeNull();
        msg.Headers!["X-Test-Key"].ToString().ShouldBe("test-value");
    }

    [Fact]
    public async Task Headers_MultipleHeaders_AllPreserved()
    {
        await using var pub = fixture.CreateClient();
        await using var sub = fixture.CreateClient();
        await pub.ConnectAsync();
        await sub.ConnectAsync();

        await using var subscription = await sub.SubscribeCoreAsync<string>("e2e.hdr.multi");
        await sub.PingAsync();

        var headers = new NatsHeaders
        {
            { "X-First", "one" },
            { "X-Second", "two" },
            { "X-Third", "three" },
        };
        await pub.PublishAsync("e2e.hdr.multi", "multi-hdr", headers: headers);

        using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
        var msg = await subscription.Msgs.ReadAsync(cts.Token);

        msg.Headers.ShouldNotBeNull();
        msg.Headers!["X-First"].ToString().ShouldBe("one");
        msg.Headers!["X-Second"].ToString().ShouldBe("two");
        msg.Headers!["X-Third"].ToString().ShouldBe("three");
    }

    [Fact]
    public async Task Headers_EmptyValue_RoundTrips()
    {
        await using var pub = fixture.CreateClient();
        await using var sub = fixture.CreateClient();
        await pub.ConnectAsync();
        await sub.ConnectAsync();

        await using var subscription = await sub.SubscribeCoreAsync<string>("e2e.hdr.empty");
        await sub.PingAsync();

        var headers = new NatsHeaders { { "X-Empty", "" } };
        await pub.PublishAsync("e2e.hdr.empty", "empty-val", headers: headers);

        using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
        var msg = await subscription.Msgs.ReadAsync(cts.Token);

        msg.Headers.ShouldNotBeNull();
        msg.Headers!.ContainsKey("X-Empty").ShouldBeTrue();
        msg.Headers!["X-Empty"].ToString().ShouldBe("");
    }
}
