package lobby

import (
	"errors"
	"strings"
	"testing"
)

func TestPolicyCanonicalCaseFold(t *testing.T) {
	policy := mustPolicy(t)
	cases := []string{
		"Andromeda",
		"andromeda",
		"ANDROMEDA",
		"  Andromeda  ",
	}
	want, err := policy.Canonical(cases[0])
	if err != nil {
		t.Fatalf("baseline canonical: %v", err)
	}
	for _, c := range cases[1:] {
		got, err := policy.Canonical(c)
		if err != nil {
			t.Fatalf("canonical %q: %v", c, err)
		}
		if got != want {
			t.Errorf("canonical %q = %q, want %q", c, got, want)
		}
	}
}

func TestPolicyCanonicalAntiFraud(t *testing.T) {
	policy := mustPolicy(t)
	want, err := policy.Canonical("pilot")
	if err != nil {
		t.Fatalf("baseline canonical: %v", err)
	}
	for _, c := range []string{"P1lot", "p1lot", "p1L0T", "P1L0t"} {
		got, err := policy.Canonical(c)
		if err != nil {
			t.Fatalf("canonical %q: %v", c, err)
		}
		if got != want {
			t.Errorf("canonical %q = %q, want %q", c, got, want)
		}
	}
}

func TestPolicyCanonicalRejectsEmpty(t *testing.T) {
	policy := mustPolicy(t)
	_, err := policy.Canonical("   ")
	if !errors.Is(err, ErrInvalidInput) {
		t.Fatalf("canonical empty: err = %v, want ErrInvalidInput", err)
	}
}

func TestPolicyCanonicalRejectsTooLong(t *testing.T) {
	policy := mustPolicy(t)
	long := strings.Repeat("a", 50)
	_, err := policy.Canonical(long)
	if !errors.Is(err, ErrInvalidInput) {
		t.Fatalf("canonical too long: err = %v, want ErrInvalidInput", err)
	}
}

func TestValidateDisplayNameRejectsControlChars(t *testing.T) {
	if _, err := ValidateDisplayName("bad\x00name"); !errors.Is(err, ErrInvalidInput) {
		t.Fatalf("ValidateDisplayName control: err = %v, want ErrInvalidInput", err)
	}
	if _, err := ValidateDisplayName("good name"); err != nil {
		t.Fatalf("ValidateDisplayName valid: err = %v", err)
	}
}

func TestPolicyWithSkeletonerOverrides(t *testing.T) {
	stub := stubSkeletoner(func(s string) string { return "fixed" })
	policy := mustPolicy(t).WithSkeletoner(stub)
	got, err := policy.Canonical("Andromeda")
	if err != nil {
		t.Fatalf("canonical with stub: %v", err)
	}
	if string(got) != "fixed" {
		t.Errorf("canonical with stub = %q, want %q", got, "fixed")
	}
}

func mustPolicy(t *testing.T) *Policy {
	t.Helper()
	p, err := NewPolicy()
	if err != nil {
		t.Fatalf("NewPolicy: %v", err)
	}
	return p
}

type stubSkeletoner func(string) string

func (s stubSkeletoner) Skeleton(in string) string { return s(in) }
