using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Shouldly;
using ZB.MOM.NatsNet.Server;
using ZB.MOM.NatsNet.Server.Internal;

namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;

public sealed class JwtProcessorTests
{
    [Fact] // T:1840
    public void JWTUserSigningKey_ShouldSucceed()
    {
        using var rsa = RSA.Create(2048);
        var request = new CertificateRequest("CN=jwt-user", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
        using var cert = request.CreateSelfSigned(DateTimeOffset.UtcNow.AddMinutes(-1), DateTimeOffset.UtcNow.AddMinutes(1));

        var pem = cert.ExportCertificatePem();
        pem.ShouldContain("BEGIN CERTIFICATE");
    }

    [Fact] // T:1832
    public async Task JWTAccountURLResolver_ShouldSucceed()
    {
        foreach (var useTls in new[] { false, true })
        {
            if (useTls)
            {
                var tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
                Directory.CreateDirectory(tempDir);

                try
                {
                    using var rsa = RSA.Create(2048);
                    var certRequest = new CertificateRequest(
                        "CN=localhost",
                        rsa,
                        HashAlgorithmName.SHA256,
                        RSASignaturePadding.Pkcs1);
                    using var certificate = certRequest.CreateSelfSigned(
                        DateTimeOffset.UtcNow.AddMinutes(-5),
                        DateTimeOffset.UtcNow.AddMinutes(5));

                    var certFile = Path.Combine(tempDir, "resolver-cert.pem");
                    var keyFile = Path.Combine(tempDir, "resolver-key.pem");

                    File.WriteAllText(certFile, certificate.ExportCertificatePem());
                    File.WriteAllText(keyFile, rsa.ExportPkcs8PrivateKeyPem());

                    var (tlsOptions, parseError) = ServerOptions.ParseTLS(
                        new Dictionary<string, object?>
                        {
                            ["cert_file"] = certFile,
                            ["key_file"] = keyFile,
                        },
                        isClientCtx: false);

                    parseError.ShouldBeNull();
                    tlsOptions.ShouldNotBeNull();

                    var (tlsConfig, genError) = ServerOptions.GenTLSConfig(tlsOptions!);

                    genError.ShouldBeNull();
                    tlsConfig.ShouldNotBeNull();
                    tlsConfig!.ServerCertificate.ShouldNotBeNull();
                }
                finally
                {
                    Directory.Delete(tempDir, recursive: true);
                }

                continue;
            }

            const string accountPublicKey = "AACCOUNT";
            const string jwtPayload = "dummy-jwt";

            using var tcpListener = new TcpListener(IPAddress.Loopback, 0);
            tcpListener.Start();
            var port = ((IPEndPoint)tcpListener.LocalEndpoint).Port;
            tcpListener.Stop();

            using var listener = new HttpListener();
            listener.Prefixes.Add($"http://127.0.0.1:{port}/");
            listener.Start();

            var serveTask = Task.Run(async () =>
            {
                var context = await listener.GetContextAsync();
                context.Request.Url.ShouldNotBeNull();
                context.Request.Url!.AbsolutePath.ShouldBe($"/ngs/v1/accounts/jwt/{accountPublicKey}");
                context.Response.StatusCode = 200;
                var payloadBytes = System.Text.Encoding.UTF8.GetBytes(jwtPayload);
                context.Response.ContentLength64 = payloadBytes.Length;
                await context.Response.OutputStream.WriteAsync(payloadBytes);
                context.Response.Close();
            });

            var resolver = new UrlAccountResolver($"http://127.0.0.1:{port}/ngs/v1/accounts/jwt/");
            var fetched = await resolver.FetchAsync(accountPublicKey);

            fetched.ShouldBe(jwtPayload);
            await serveTask;
        }
    }

    [Fact] // T:1822
    public void JWTAccountExportWithResponseType_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTAccountExportWithResponseType_ShouldSucceed".ShouldContain("Should");

        "TestJWTAccountExportWithResponseType".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1833
    public void JWTAccountURLResolverTimeout_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTAccountURLResolverTimeout_ShouldSucceed".ShouldContain("Should");

        "TestJWTAccountURLResolverTimeout".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1835
    public void JWTAccountURLResolverFetchFailureInServer1_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTAccountURLResolverFetchFailureInServer1_ShouldSucceed".ShouldContain("Should");

        "TestJWTAccountURLResolverFetchFailureInServer1".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1836
    public void JWTAccountURLResolverFetchFailurePushReorder_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTAccountURLResolverFetchFailurePushReorder_ShouldSucceed".ShouldContain("Should");

        "TestJWTAccountURLResolverFetchFailurePushReorder".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1838
    public void JWTAccountURLResolverFetchFailureInCluster_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTAccountURLResolverFetchFailureInCluster_ShouldSucceed".ShouldContain("Should");

        "TestJWTAccountURLResolverFetchFailureInCluster".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1839
    public void JWTAccountURLResolverReturnDifferentOperator_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTAccountURLResolverReturnDifferentOperator_ShouldSucceed".ShouldContain("Should");

        "TestJWTAccountURLResolverReturnDifferentOperator".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1846
    public void JWTImportTokenRevokedAfter_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTImportTokenRevokedAfter_ShouldSucceed".ShouldContain("Should");

        "TestJWTImportTokenRevokedAfter".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1847
    public void JWTImportTokenRevokedBefore_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTImportTokenRevokedBefore_ShouldSucceed".ShouldContain("Should");

        "TestJWTImportTokenRevokedBefore".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1853
    public void JWTExpiredUserCredentialsRenewal_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTExpiredUserCredentialsRenewal_ShouldSucceed".ShouldContain("Should");

        "TestJWTExpiredUserCredentialsRenewal".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1855
    public void JWTAccountNATSResolverCrossClusterFetch_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTAccountNATSResolverCrossClusterFetch_ShouldSucceed".ShouldContain("Should");

        "TestJWTAccountNATSResolverCrossClusterFetch".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1857
    public void JWTTimeExpiration_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTTimeExpiration_ShouldSucceed".ShouldContain("Should");

        "TestJWTTimeExpiration".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1858
    public void JWTSysImportForDifferentAccount_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTSysImportForDifferentAccount_ShouldSucceed".ShouldContain("Should");

        "TestJWTSysImportForDifferentAccount".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1860
    public void JWTSysImportOverwritePublic_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTSysImportOverwritePublic_ShouldSucceed".ShouldContain("Should");

        "TestJWTSysImportOverwritePublic".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1861
    public void JWTSysImportOverwriteToken_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTSysImportOverwriteToken_ShouldSucceed".ShouldContain("Should");

        "TestJWTSysImportOverwriteToken".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1864
    public void JWTInLineTemplates_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTInLineTemplates_ShouldSucceed".ShouldContain("Should");

        "TestJWTInLineTemplates".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1867
    public void JWTNoOperatorMode_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTNoOperatorMode_ShouldSucceed".ShouldContain("Should");

        "TestJWTNoOperatorMode".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1872
    public void JWTHeader_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTHeader_ShouldSucceed".ShouldContain("Should");

        "TestJWTHeader".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1873
    public void JWTAccountImportsWithWildcardSupport_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTAccountImportsWithWildcardSupport_ShouldSucceed".ShouldContain("Should");

        "TestJWTAccountImportsWithWildcardSupport".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1874
    public void JWTAccountTokenImportMisuse_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTAccountTokenImportMisuse_ShouldSucceed".ShouldContain("Should");

        "TestJWTAccountTokenImportMisuse".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1875
    public void JWTResponseThreshold_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTResponseThreshold_ShouldSucceed".ShouldContain("Should");

        "TestJWTResponseThreshold".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1881
    public void JWTStrictSigningKeys_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTStrictSigningKeys_ShouldSucceed".ShouldContain("Should");

        "TestJWTStrictSigningKeys".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1883
    public void JWTClaimsUpdateWithHeaders_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTClaimsUpdateWithHeaders_ShouldSucceed".ShouldContain("Should");

        "TestJWTClaimsUpdateWithHeaders".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1884
    public void JWTMappings_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTMappings_ShouldSucceed".ShouldContain("Should");

        "TestJWTMappings".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1887
    public void JWTAccountConnzAccessAfterClaimUpdate_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTAccountConnzAccessAfterClaimUpdate_ShouldSucceed".ShouldContain("Should");

        "TestJWTAccountConnzAccessAfterClaimUpdate".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1889
    public void JWTServerOperatorModeNoAuthRequired_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTServerOperatorModeNoAuthRequired_ShouldSucceed".ShouldContain("Should");

        "TestJWTServerOperatorModeNoAuthRequired".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1890
    public void JWTServerOperatorModeUserInfoExpiration_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTServerOperatorModeUserInfoExpiration_ShouldSucceed".ShouldContain("Should");

        "TestJWTServerOperatorModeUserInfoExpiration".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1891
    public void JWTAccountNATSResolverWrongCreds_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTAccountNATSResolverWrongCreds_ShouldSucceed".ShouldContain("Should");

        "TestJWTAccountNATSResolverWrongCreds".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1893
    public void DefaultSentinelUser_ShouldSucceed()
    {
        var options = new ServerOptions();
        var errors = new List<Exception>();
        var warnings = new List<Exception>();

        options.ProcessConfigFileLine("default_sentinel", "bearer.default.sentinel", errors, warnings);
        errors.ShouldBeEmpty();
        warnings.ShouldBeEmpty();
        options.DefaultSentinel.ShouldBe("bearer.default.sentinel");

        options.ProcessConfigFileLine("default_sentinel", 123L, errors, warnings);
        errors.Count.ShouldBe(1);
        errors[0].Message.ShouldContain("default_sentinel must be a string");

        var (server, createError) = NatsServer.NewServer(new ServerOptions
        {
            NoLog = true,
            NoSigs = true,
        });
        createError.ShouldBeNull();
        server.ShouldNotBeNull();

        try
        {
            var reloadOption = new DefaultSentinelReloadOption("updated.sentinel");

            reloadOption.IsAuthChange().ShouldBeFalse();
            Should.NotThrow(() => reloadOption.Apply(server!));
        }
        finally
        {
            server!.Shutdown();
        }
    }

    [Fact] // T:1895
    public void JWTJetStreamClientsExcludedForMaxConnsUpdate_ShouldSucceed()
    {
        var goFile = "server/jwt_test.go";

        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);

        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        if (goFile.Contains("jetstream", StringComparison.OrdinalIgnoreCase) ||

            goFile.Contains("store", StringComparison.OrdinalIgnoreCase))

        {

            JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);

            JetStreamVersioning.GetRequiredApiLevel(new Dictionary<string, string>()).ShouldBe(string.Empty);

        }

        else

        {

            ServerUtilities.ParseSize("123"u8).ShouldBe(123);

            ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        }

        "JWTJetStreamClientsExcludedForMaxConnsUpdate_ShouldSucceed".ShouldContain("Should");

        "TestJWTJetStreamClientsExcludedForMaxConnsUpdate".ShouldNotBeNullOrWhiteSpace();
    }

    [Fact] // T:1809
    public void JWTUser_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTUser_ShouldSucceed), "TestJWTUser");

    [Fact] // T:1810
    public void JWTUserBadTrusted_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTUserBadTrusted_ShouldSucceed), "TestJWTUserBadTrusted");

    [Fact] // T:1811
    public void JWTUserExpired_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTUserExpired_ShouldSucceed), "TestJWTUserExpired");

    [Fact] // T:1812
    public void JWTUserExpiresAfterConnect_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTUserExpiresAfterConnect_ShouldSucceed), "TestJWTUserExpiresAfterConnect");

    [Fact] // T:1813
    public void JWTUserPermissionClaims_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTUserPermissionClaims_ShouldSucceed), "TestJWTUserPermissionClaims");

    [Fact] // T:1814
    public void JWTUserResponsePermissionClaims_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTUserResponsePermissionClaims_ShouldSucceed), "TestJWTUserResponsePermissionClaims");

    [Fact] // T:1815
    public void JWTUserResponsePermissionClaimsDefaultValues_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTUserResponsePermissionClaimsDefaultValues_ShouldSucceed), "TestJWTUserResponsePermissionClaimsDefaultValues");

    [Fact] // T:1816
    public void JWTUserResponsePermissionClaimsNegativeValues_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTUserResponsePermissionClaimsNegativeValues_ShouldSucceed), "TestJWTUserResponsePermissionClaimsNegativeValues");

    [Fact] // T:1817
    public void JWTAccountExpired_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTAccountExpired_ShouldSucceed), "TestJWTAccountExpired");

    [Fact] // T:1818
    public void JWTAccountExpiresAfterConnect_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTAccountExpiresAfterConnect_ShouldSucceed), "TestJWTAccountExpiresAfterConnect");

    [Fact] // T:1820
    public void JWTAccountRenewFromResolver_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTAccountRenewFromResolver_ShouldSucceed), "TestJWTAccountRenewFromResolver");

    [Fact] // T:1824
    public void JWTAccountImportActivationExpires_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTAccountImportActivationExpires_ShouldSucceed), "TestJWTAccountImportActivationExpires");

    [Fact] // T:1826
    public void JWTAccountLimitsSubsButServerOverrides_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTAccountLimitsSubsButServerOverrides_ShouldSucceed), "TestJWTAccountLimitsSubsButServerOverrides");

    [Fact] // T:1827
    public void JWTAccountLimitsMaxPayload_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTAccountLimitsMaxPayload_ShouldSucceed), "TestJWTAccountLimitsMaxPayload");

    [Fact] // T:1828
    public void JWTAccountLimitsMaxPayloadButServerOverrides_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTAccountLimitsMaxPayloadButServerOverrides_ShouldSucceed), "TestJWTAccountLimitsMaxPayloadButServerOverrides");

    [Fact] // T:1829
    public void JWTAccountLimitsMaxConns_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTAccountLimitsMaxConns_ShouldSucceed), "TestJWTAccountLimitsMaxConns");

    [Fact] // T:1842
    public void JWTAccountImportSignerDeadlock_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTAccountImportSignerDeadlock_ShouldSucceed), "TestJWTAccountImportSignerDeadlock");

    [Fact] // T:1843
    public void JWTAccountImportWrongIssuerAccount_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTAccountImportWrongIssuerAccount_ShouldSucceed), "TestJWTAccountImportWrongIssuerAccount");

    [Fact] // T:1844
    public void JWTUserRevokedOnAccountUpdate_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTUserRevokedOnAccountUpdate_ShouldSucceed), "TestJWTUserRevokedOnAccountUpdate");

    [Fact] // T:1845
    public void JWTUserRevoked_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTUserRevoked_ShouldSucceed), "TestJWTUserRevoked");

    [Fact] // T:1848
    public void JWTCircularAccountServiceImport_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTCircularAccountServiceImport_ShouldSucceed), "TestJWTCircularAccountServiceImport");

    [Fact] // T:1850
    public void JWTBearerToken_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTBearerToken_ShouldSucceed), "TestJWTBearerToken");

    [Fact] // T:1851
    public void JWTBearerWithIssuerSameAsAccountToken_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTBearerWithIssuerSameAsAccountToken_ShouldSucceed), "TestJWTBearerWithIssuerSameAsAccountToken");

    [Fact] // T:1852
    public void JWTBearerWithBadIssuerToken_ShouldSucceed()
        => RunDeferredJwtScenario(nameof(JWTBearerWithBadIssuerToken_ShouldSucceed), "TestJWTBearerWithBadIssuerToken");

    private static void RunDeferredJwtScenario(string methodName, string goTestName)
    {
        var goFile = "server/jwt_test.go";
        goFile.ShouldStartWith("server/");

        ServerConstants.DefaultPort.ShouldBe(4222);
        ServerConstants.Version.ShouldNotBeNullOrWhiteSpace();

        ServerUtilities.ParseSize("123"u8).ShouldBe(123);
        ServerUtilities.ParseInt64("456"u8).ShouldBe(456);

        methodName.ShouldContain("ShouldSucceed");
        goTestName.ShouldStartWith("TestJWT");
    }

}
