using Microsoft.Extensions.Logging.Abstractions;
using NATS.Server.Subscriptions;

namespace NATS.Server.Tests;

public class SubjectTransformIntegrationTests
{
    [Fact]
    public void Server_compiles_subject_mappings()
    {
        var options = new NatsOptions
        {
            SubjectMappings = new Dictionary<string, string>
            {
                ["src.*"] = "dest.{{wildcard(1)}}",
                ["orders.*.*"] = "processed.{{wildcard(2)}}.{{wildcard(1)}}",
            },
        };
        using var server = new NatsServer(options, NullLoggerFactory.Instance);

        // Server should have started without errors (transforms compiled)
        server.Port.ShouldBe(4222);
    }

    [Fact]
    public void Server_ignores_null_subject_mappings()
    {
        var options = new NatsOptions { SubjectMappings = null };
        using var server = new NatsServer(options, NullLoggerFactory.Instance);
        server.Port.ShouldBe(4222);
    }

    [Fact]
    public void Server_ignores_empty_subject_mappings()
    {
        var options = new NatsOptions { SubjectMappings = new Dictionary<string, string>() };
        using var server = new NatsServer(options, NullLoggerFactory.Instance);
        server.Port.ShouldBe(4222);
    }

    [Fact]
    public void Server_logs_warning_for_invalid_mapping()
    {
        var options = new NatsOptions
        {
            SubjectMappings = new Dictionary<string, string>
            {
                [""] = "dest", // invalid empty source becomes ">" which is valid
            },
        };
        using var server = new NatsServer(options, NullLoggerFactory.Instance);
        // Should not throw, just log a warning and skip
        server.Port.ShouldBe(4222);
    }

    [Fact]
    public void SubjectTransform_applies_first_matching_rule()
    {
        // Unit test the transform application logic directly
        var t1 = SubjectTransform.Create("src.*", "dest.{{wildcard(1)}}");
        var t2 = SubjectTransform.Create("src.*", "other.{{wildcard(1)}}");
        t1.ShouldNotBeNull();
        t2.ShouldNotBeNull();

        var transforms = new[] { t1, t2 };
        string subject = "src.hello";

        // Apply transforms -- first match wins
        foreach (var transform in transforms)
        {
            var mapped = transform.Apply(subject);
            if (mapped != null)
            {
                subject = mapped;
                break;
            }
        }

        subject.ShouldBe("dest.hello");
    }

    [Fact]
    public void SubjectTransform_non_matching_subject_unchanged()
    {
        var t = SubjectTransform.Create("src.*", "dest.{{wildcard(1)}}");
        t.ShouldNotBeNull();

        var result = t.Apply("other.hello");
        result.ShouldBeNull(); // No match
    }
}
