// Copyright 2012-2026 The NATS Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System.Reflection;
using Shouldly;
using ZB.MOM.NatsNet.Server.Auth;

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

public sealed class NonceRequiredTests
{
    [Fact]
    public void NonceRequiredInternal_NoConditions_ReturnsFalse()
    {
        var server = CreateServer();
        server.NonceRequiredInternal().ShouldBeFalse();
    }

    [Fact]
    public void NonceRequiredInternal_AlwaysEnableNonceOptionSet_ReturnsTrue()
    {
        var server = CreateServer();
        var opts = server.GetOpts();
        opts.AlwaysEnableNonce = true;
        server.SetOpts(opts);

        server.NonceRequiredInternal().ShouldBeTrue();
    }

    [Fact]
    public void NonceRequiredInternal_NkeysConfigured_ReturnsTrue()
    {
        var server = CreateServer();
        SetPrivateField(server, "_nkeys", new Dictionary<string, NkeyUser>
        {
            ["UAEXAMPLE"] = new() { Nkey = "UAEXAMPLE" },
        });

        server.NonceRequiredInternal().ShouldBeTrue();
    }

    [Fact]
    public void NonceRequiredInternal_TrustedKeysPresent_ReturnsTrue()
    {
        var server = CreateServer();
        SetPrivateField(server, "_trustedKeys", new List<string> { "OPKEY" });

        server.NonceRequiredInternal().ShouldBeTrue();
    }

    [Fact]
    public void NonceRequiredInternal_ProxiesKeyPairsPresent_ReturnsTrue()
    {
        var server = CreateServer();
        var proxiesField = typeof(NatsServer).GetField("_proxiesKeyPairs", BindingFlags.Instance | BindingFlags.NonPublic);
        proxiesField.ShouldNotBeNull();
        var proxies = proxiesField!.GetValue(server).ShouldBeOfType<List<object>>();
        proxies.Add(new object());

        server.NonceRequiredInternal().ShouldBeTrue();
    }

    private static NatsServer CreateServer()
    {
        var (server, error) = NatsServer.NewServer(new ServerOptions());
        error.ShouldBeNull();
        server.ShouldNotBeNull();
        return server!;
    }

    private static void SetPrivateField<T>(NatsServer server, string fieldName, T value)
    {
        var field = typeof(NatsServer).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
        field.ShouldNotBeNull();
        field!.SetValue(server, value);
    }
}
