package account

import (
	"strings"
	"testing"
	"time"
)

func TestValidateDisplayName(t *testing.T) {
	cases := map[string]struct {
		in   string
		want string
		ok   bool
	}{
		"plain":               {"Kaya", "Kaya", true},
		"cyrillic":            {"Кая", "Кая", true},
		"dot underscore mix":  {"Name_P. Last", "Name_P. Last", true},
		"single dot":          {"Mr.Smith", "Mr.Smith", true},
		"dot then space":      {"Mr. Smith", "Mr. Smith", true},
		"trim surrounding":    {"  Kaya  ", "Kaya", true},
		"adjacent specials":   {"Name P._Last", "", false},
		"two spaces":          {"Name  Last", "", false},
		"leading special":     {"_Name", "", false},
		"trailing underscore": {"Name_", "", false},
		"trailing dot ok":     {"Anna B.", "Anna B.", true},
		"double trailing dot": {"Name..", "", false},
		"trailing digit ok":   {"Name2", "Name2", true},
		"trailing year ok":    {"Аня2007", "Аня2007", true},
		"five digits ok":      {"Player12345", "Player12345", true},
		"six digits rejected": {"Player123456", "", false},
		"mid digit rejected":  {"Dark2Wolf", "", false},
		"all digits rejected": {"12345", "", false},
		"digit then dot":      {"Name2.", "", false},
		"dot then digit":      {"Anna B.2", "", false},
		"sep plus digits ok":  {"Night.Fox2007", "Night.Fox2007", true},     // "." is the only special; digits do not count
		"max specials+digits": {"a.a.a.a.a.a2007", "a.a.a.a.a.a2007", true}, // 5 dots + a digit run still passes
		"blank":               {"   ", "", false},
		"too long":            {strings.Repeat("a", 33), "", false},
		"five specials ok":    {"a.a.a.a.a.a", "a.a.a.a.a.a", true},           // 5 dots
		"six specials":        {"a.a.a.a.a.a.a", "", false},                   // 6 dots
		"initials spaces ok":  {"J. R. R. Tolkien", "J. R. R. Tolkien", true}, // 3 dots; spaces don't count
	}
	for name, tc := range cases {
		t.Run(name, func(t *testing.T) {
			got, err := ValidateDisplayName(tc.in)
			if tc.ok != (err == nil) || (tc.ok && got != tc.want) {
				t.Fatalf("ValidateDisplayName(%q) = (%q, err=%v), want (%q, ok=%v)", tc.in, got, err, tc.want, tc.ok)
			}
		})
	}
}

func TestValidateAwayWindow(t *testing.T) {
	hm := func(h, m int) time.Time { return time.Date(0, 1, 1, h, m, 0, 0, time.UTC) }
	cases := map[string]struct {
		start, end time.Time
		ok         bool
	}{
		"8h overnight": {hm(22, 0), hm(6, 0), true},
		"12h exact":    {hm(0, 0), hm(12, 0), true},
		"13h daytime":  {hm(8, 0), hm(21, 0), false},
		"zero window":  {hm(7, 0), hm(7, 0), true},
		"13h wrap":     {hm(20, 0), hm(9, 0), false},
	}
	for name, tc := range cases {
		t.Run(name, func(t *testing.T) {
			if err := validateAwayWindow(tc.start, tc.end); tc.ok != (err == nil) {
				t.Fatalf("validateAwayWindow = %v, want ok=%v", err, tc.ok)
			}
		})
	}
}

func TestResolveAndValidZone(t *testing.T) {
	offsetOf := func(name string) int {
		_, off := time.Date(2024, 1, 1, 12, 0, 0, 0, ResolveZone(name)).Zone()
		return off
	}
	if got := offsetOf("+03:00"); got != 3*3600 {
		t.Errorf("+03:00 offset = %d, want 10800", got)
	}
	if got := offsetOf("-05:30"); got != -(5*3600 + 30*60) {
		t.Errorf("-05:30 offset = %d", got)
	}
	if ResolveZone("nonsense-zone") != time.UTC {
		t.Error("unknown zone should resolve to UTC")
	}
	for _, ok := range []string{"+05:45", "-12:00", "+14:00", "Europe/Moscow", "UTC"} {
		if !validZone(ok) {
			t.Errorf("validZone(%q) = false, want true", ok)
		}
	}
	for _, bad := range []string{"+15:00", "03:00", "+3:00", "nope", "+05:99"} {
		if validZone(bad) {
			t.Errorf("validZone(%q) = true, want false", bad)
		}
	}
}
