package ns

import (
	"testing"
)

// TestValidateName_Acceptable verifies normal names pass.
func TestValidateName_Acceptable(t *testing.T) {
	ok := []string{
		"prod",
		"dev",
		"team_a",
		"team-b",
		"ns1",
		"a.b.c",
		"0",
		"with-dashes-and_underscores.and.dots",
		"CAPS",
	}
	for _, name := range ok {
		t.Run(name, func(t *testing.T) {
			if err := ValidateName(name); err != nil {
				t.Errorf("ValidateName(%q) = %v, want nil", name, err)
			}
		})
	}
}

// TestValidateName_Rejected verifies traversal/injection names fail.
func TestValidateName_Rejected(t *testing.T) {
	bad := []string{
		"",
		"..",
		"../etc",
		"foo/../bar",
		"/etc",
		"etc/",
		"foo/bar",
		"foo\\bar",
		"-x",
		"--flag",
		"cluster",
		"_defaults", // reserved names: cluster enforced here; _defaults
		// is intentionally NOT rejected by ValidateName (it's the
		// implicit root; the CLI prevents creating it). We accept it
		// in the validator and let the CLI enforce the create rule.
		"a\x00b",
		"with space",
		"tab\there",
		"newline\nname",
	}
	for _, name := range bad {
		t.Run(name, func(t *testing.T) {
			// _defaults is a special case: it's a reserved name but
			// ValidateName does NOT reject it (only "cluster" is
			// rejected at this layer; _defaults is the implicit root).
			if name == "_defaults" {
				if err := ValidateName(name); err != nil {
					t.Errorf("ValidateName(%q) should pass (implicit root)", name)
				}
				return
			}
			if err := ValidateName(name); err == nil {
				t.Errorf("ValidateName(%q) = nil, want error", name)
			}
		})
	}
}

// TestValidateName_Length verifies the 128-char limit.
func TestValidateName_Length(t *testing.T) {
	long := make([]byte, 129)
	for i := range long {
		long[i] = 'a'
	}
	if err := ValidateName(string(long)); err == nil {
		t.Error("129-char name should be rejected")
	}
	exact := make([]byte, 128)
	for i := range exact {
		exact[i] = 'a'
	}
	if err := ValidateName(string(exact)); err != nil {
		t.Errorf("128-char name should pass: %v", err)
	}
}

// FuzzValidateName is a fuzz test ensuring ValidateName never panics
// and rejects any name containing "..", "/", or control chars.
func FuzzValidateName(f *testing.F) {
	f.Add("prod")
	f.Add("..")
	f.Add("/etc")
	f.Add("-flag")
	f.Add("a\x00b")
	f.Fuzz(func(t *testing.T, name string) {
		// ValidateName must never panic.
		_ = ValidateName(name)
	})
}
