// Copyright 2016-2025 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.Security.Authentication;
using System.Net.Security;
using Shouldly;
using ZB.MOM.NatsNet.Server.Auth;

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

/// <summary>
/// Tests for CipherSuites definitions.
/// Mirrors Go ciphersuites.go functionality.
/// </summary>
public class CipherSuitesTests
{
    [Fact]
    public void Init_CalledMultipleTimes_RemainsIdempotent()
    {
        var beforeCount = CipherSuites.CipherMap.Count;
        var beforeByIdCount = CipherSuites.CipherMapById.Count;

        CipherSuites.Init();
        CipherSuites.Init();

        CipherSuites.CipherMap.Count.ShouldBe(beforeCount);
        CipherSuites.CipherMapById.Count.ShouldBe(beforeByIdCount);
    }

    [Fact]
    public void CipherMap_ContainsTls13Suites()
    {
        CipherSuites.CipherMap.ShouldNotBeEmpty();
        // At minimum, TLS 1.3 suites should be present.
        CipherSuites.CipherMap.ShouldContainKey("TLS_AES_256_GCM_SHA384");
        CipherSuites.CipherMap.ShouldContainKey("TLS_AES_128_GCM_SHA256");
    }

    [Fact]
    public void CipherMapById_ContainsTls13Suites()
    {
        CipherSuites.CipherMapById.ShouldNotBeEmpty();
        CipherSuites.CipherMapById.ShouldContainKey(TlsCipherSuite.TLS_AES_256_GCM_SHA384);
    }

    [Fact]
    public void CipherMap_CaseInsensitiveLookup()
    {
        // The map uses OrdinalIgnoreCase comparer.
        CipherSuites.CipherMap.ShouldContainKey("tls_aes_256_gcm_sha384");
    }

    [Fact]
    public void DefaultCipherSuites_ReturnsNonEmptyList()
    {
        var defaults = CipherSuites.DefaultCipherSuites();
        defaults.ShouldNotBeEmpty();
        defaults.Length.ShouldBeGreaterThan(0);
    }

    [Fact]
    public void DefaultCipherSuites_ContainsSecureSuites()
    {
        var defaults = CipherSuites.DefaultCipherSuites();
        defaults.ShouldContain(TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384);
        defaults.ShouldContain(TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384);
    }

    [Fact]
    public void CurvePreferenceMap_ContainsExpectedCurves()
    {
        CipherSuites.CurvePreferenceMap.ShouldContainKey("X25519");
        CipherSuites.CurvePreferenceMap.ShouldContainKey("CurveP256");
        CipherSuites.CurvePreferenceMap.ShouldContainKey("CurveP384");
        CipherSuites.CurvePreferenceMap.ShouldContainKey("CurveP521");
    }

    [Fact]
    public void DefaultCurvePreferences_ReturnsExpectedOrder()
    {
        var prefs = CipherSuites.DefaultCurvePreferences();
        prefs.Length.ShouldBeGreaterThanOrEqualTo(4);
        prefs[0].ShouldBe("X25519");
    }
}
