package tlsutil

import (
	"crypto/tls"
	"testing"

	"codeberg.org/VARASYS/ZDDC/zddc/internal/config"
)

// TestTLSConfig_NoneMode: TLSMode=="none" returns no config and useTLS=false.
func TestTLSConfig_NoneMode(t *testing.T) {
	tlsCfg, useTLS, err := TLSConfig(config.Config{TLSMode: "none"})
	if err != nil {
		t.Fatalf("TLSConfig(none): %v", err)
	}
	if useTLS {
		t.Errorf("useTLS = true, want false for TLSMode=none")
	}
	if tlsCfg != nil {
		t.Errorf("tlsCfg = %+v, want nil for TLSMode=none", tlsCfg)
	}
}

// TestTLSConfig_SelfSignedHardenedDefaults: the self-signed path returns a
// config that conforms to NIST SP 800-52 Rev. 2 — TLS 1.2 minimum, the
// AEAD-only cipher allowlist, and the X25519/P-256/P-384 curve list.
func TestTLSConfig_SelfSignedHardenedDefaults(t *testing.T) {
	tlsCfg, useTLS, err := TLSConfig(config.Config{TLSMode: "selfsigned"})
	if err != nil {
		t.Fatalf("TLSConfig(selfsigned): %v", err)
	}
	if !useTLS {
		t.Fatal("useTLS = false, want true")
	}
	if tlsCfg == nil {
		t.Fatal("tlsCfg = nil")
	}

	if tlsCfg.MinVersion != tls.VersionTLS12 {
		t.Errorf("MinVersion = %#x, want TLS 1.2 (%#x)", tlsCfg.MinVersion, tls.VersionTLS12)
	}

	wantCiphers := map[uint16]bool{
		tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: true,
		tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: true,
		tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:   true,
		tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:   true,
		tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305:  true,
		tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305:    true,
	}
	if len(tlsCfg.CipherSuites) != len(wantCiphers) {
		t.Errorf("CipherSuites count = %d, want %d", len(tlsCfg.CipherSuites), len(wantCiphers))
	}
	for _, c := range tlsCfg.CipherSuites {
		if !wantCiphers[c] {
			t.Errorf("CipherSuites contains unexpected suite %#x; allowlist is the NIST SP 800-52 Rev. 2 set", c)
		}
	}

	wantCurves := map[tls.CurveID]bool{
		tls.X25519:    true,
		tls.CurveP256: true,
		tls.CurveP384: true,
	}
	if len(tlsCfg.CurvePreferences) != len(wantCurves) {
		t.Errorf("CurvePreferences count = %d, want %d", len(tlsCfg.CurvePreferences), len(wantCurves))
	}
	for _, c := range tlsCfg.CurvePreferences {
		if !wantCurves[c] {
			t.Errorf("CurvePreferences contains unexpected curve %v", c)
		}
	}

	if len(tlsCfg.Certificates) != 1 {
		t.Errorf("Certificates count = %d, want 1", len(tlsCfg.Certificates))
	}
}

// TestTLSConfig_NoWeakCiphers: the allowlist must not include any of the
// federally-deprecated suites — CBC-mode, RC4, 3DES, SHA-1, NULL, EXPORT.
// This is a guardrail against accidental regressions if the list is edited.
func TestTLSConfig_NoWeakCiphers(t *testing.T) {
	tlsCfg, _, err := TLSConfig(config.Config{TLSMode: "selfsigned"})
	if err != nil {
		t.Fatalf("TLSConfig: %v", err)
	}
	weak := map[uint16]string{
		tls.TLS_RSA_WITH_AES_128_CBC_SHA:        "AES-128-CBC-SHA (CBC mode)",
		tls.TLS_RSA_WITH_AES_256_CBC_SHA:        "AES-256-CBC-SHA (CBC mode)",
		tls.TLS_RSA_WITH_AES_128_GCM_SHA256:     "RSA-AES-128-GCM (no forward secrecy)",
		tls.TLS_RSA_WITH_AES_256_GCM_SHA384:     "RSA-AES-256-GCM (no forward secrecy)",
		tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:  "ECDHE-RSA-AES-128-CBC-SHA (CBC mode)",
		tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:  "ECDHE-RSA-AES-256-CBC-SHA (CBC mode)",
		tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: "3DES",
		tls.TLS_RSA_WITH_RC4_128_SHA:            "RC4",
	}
	for _, c := range tlsCfg.CipherSuites {
		if name, bad := weak[c]; bad {
			t.Errorf("CipherSuites includes federally-deprecated suite: %s (%#x)", name, c)
		}
	}
}
