using NATS.Server.Configuration;
using NATS.Server.Gateways;

namespace NATS.Server.Gateways.Tests.Gateways;

public class GatewayReplyAndConfigParityBatch1Tests
{
    [Fact]
    public void HasGatewayReplyPrefix_accepts_new_and_old_prefixes()
    {
        ReplyMapper.HasGatewayReplyPrefix("_GR_.clusterA.reply").ShouldBeTrue();
        ReplyMapper.HasGatewayReplyPrefix("$GR.clusterA.reply").ShouldBeTrue();
        ReplyMapper.HasGatewayReplyPrefix("_INBOX.reply").ShouldBeFalse();
    }

    [Fact]
    public void IsGatewayRoutedSubject_reports_old_prefix_flag()
    {
        ReplyMapper.IsGatewayRoutedSubject("_GR_.C1.r", out var newPrefixOldFlag).ShouldBeTrue();
        newPrefixOldFlag.ShouldBeFalse();

        ReplyMapper.IsGatewayRoutedSubject("$GR.C1.r", out var oldPrefixOldFlag).ShouldBeTrue();
        oldPrefixOldFlag.ShouldBeTrue();
    }

    [Fact]
    public void TryRestoreGatewayReply_handles_old_prefix_format()
    {
        ReplyMapper.TryRestoreGatewayReply("$GR.clusterA.reply.one", out var restored).ShouldBeTrue();
        restored.ShouldBe("reply.one");
    }

    [Fact]
    public void GatewayHash_helpers_are_deterministic_and_expected_length()
    {
        var hash1 = ReplyMapper.ComputeGatewayHash("east");
        var hash2 = ReplyMapper.ComputeGatewayHash("east");
        var oldHash1 = ReplyMapper.ComputeOldGatewayHash("east");
        var oldHash2 = ReplyMapper.ComputeOldGatewayHash("east");

        hash1.ShouldBe(hash2);
        oldHash1.ShouldBe(oldHash2);
        hash1.Length.ShouldBe(ReplyMapper.GatewayHashLen);
        oldHash1.Length.ShouldBe(ReplyMapper.OldGatewayHashLen);
    }

    [Fact]
    public void Legacy_prefixed_reply_extracts_cluster_and_not_hash()
    {
        ReplyMapper.TryExtractClusterId("$GR.clusterB.inbox.reply", out var cluster).ShouldBeTrue();
        cluster.ShouldBe("clusterB");
        ReplyMapper.TryExtractHash("$GR.clusterB.inbox.reply", out _).ShouldBeFalse();
    }

    [Fact]
    public void RemoteGatewayOptions_clone_deep_copies_url_list()
    {
        var original = new RemoteGatewayOptions
        {
            Name = "gw-west",
            Urls = ["nats://127.0.0.1:7522", "nats://127.0.0.1:7523"],
        };

        var clone = original.Clone();
        clone.ShouldNotBeSameAs(original);
        clone.Name.ShouldBe(original.Name);
        clone.Urls.ShouldBe(original.Urls);

        clone.Urls.Add("nats://127.0.0.1:7524");
        original.Urls.Count.ShouldBe(2);
    }

    [Fact]
    public void ValidateGatewayOptions_checks_required_fields()
    {
        GatewayManager.ValidateGatewayOptions(new GatewayOptions
        {
            Name = "gw",
            Host = "127.0.0.1",
            Port = 7222,
            Remotes = ["127.0.0.1:8222"],
        }, out var error).ShouldBeTrue();
        error.ShouldBeNull();

        GatewayManager.ValidateGatewayOptions(new GatewayOptions { Port = 7222 }, out error).ShouldBeFalse();
        error.ShouldNotBeNull();
        error.ShouldContain("name");

        GatewayManager.ValidateGatewayOptions(new GatewayOptions { Name = "gw", Port = -1 }, out error).ShouldBeFalse();
        error.ShouldNotBeNull();
        error.ShouldContain("0-65535");

        GatewayManager.ValidateGatewayOptions(new GatewayOptions { Name = "gw", Port = 7222, Remotes = [""] }, out error).ShouldBeFalse();
        error.ShouldNotBeNull();
        error.ShouldContain("cannot be empty");
    }

    [Fact]
    public void Gateway_tls_warning_constant_is_present()
    {
        GatewayManager.GatewayTlsInsecureWarning.ShouldNotBeNullOrWhiteSpace();
        GatewayManager.GatewayTlsInsecureWarning.ShouldContain("TLS");
    }
}
