package account

import (
	"context"
	"errors"
	"slices"
	"strings"
	"testing"
	"time"

	"github.com/google/uuid"
)

// TestUpdateProfileValidation checks that bad fields are rejected before any
// database access, so a nil-backed Store is enough to exercise the guards. It also
// confirms UpdateProfile wires the validators (name format, away window,
// offset/IANA timezone), not just their unit tests in validate_test.go.
func TestUpdateProfileValidation(t *testing.T) {
	s := &Store{}
	base := ProfileUpdate{DisplayName: "Kaya", PreferredLanguage: "en", TimeZone: "UTC", VariantPreferences: []string{"erudit_ru"}}
	hm := func(h, m int) time.Time { return time.Date(0, 1, 1, h, m, 0, 0, time.UTC) }
	tests := []struct {
		name string
		mut  func(p *ProfileUpdate)
	}{
		{"unknown language", func(p *ProfileUpdate) { p.PreferredLanguage = "fr" }},
		{"invalid timezone", func(p *ProfileUpdate) { p.TimeZone = "Mars/Olympus" }},
		{"bad offset timezone", func(p *ProfileUpdate) { p.TimeZone = "+15:00" }},
		{"over-long name", func(p *ProfileUpdate) { p.DisplayName = strings.Repeat("x", maxDisplayName+1) }},
		{"bad name layout", func(p *ProfileUpdate) { p.DisplayName = "Bad__Name" }},
		{"away over 12h", func(p *ProfileUpdate) { p.AwayStart, p.AwayEnd = hm(8, 0), hm(21, 0) }},
		{"empty variant preferences", func(p *ProfileUpdate) { p.VariantPreferences = nil }},
		{"unknown variant preference", func(p *ProfileUpdate) { p.VariantPreferences = []string{"chess"} }},
	}
	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			p := base
			tc.mut(&p)
			if _, err := s.UpdateProfile(context.Background(), uuid.New(), p); !errors.Is(err, ErrInvalidProfile) {
				t.Fatalf("err = %v, want ErrInvalidProfile", err)
			}
		})
	}
}

// TestValidateVariantPreferences checks the cleaning of a profile's variant set:
// duplicates collapse, the result is canonically ordered (Erudit, Russian Scrabble,
// English) regardless of input order, and an empty or unknown set is rejected.
func TestValidateVariantPreferences(t *testing.T) {
	got, err := validateVariantPreferences([]string{"scrabble_en", "erudit_ru", "scrabble_en"})
	if err != nil {
		t.Fatalf("validate: %v", err)
	}
	if want := []string{"erudit_ru", "scrabble_en"}; !slices.Equal(got, want) {
		t.Fatalf("got %v, want %v", got, want)
	}
	if _, err := validateVariantPreferences(nil); !errors.Is(err, ErrInvalidProfile) {
		t.Fatalf("empty err = %v, want ErrInvalidProfile", err)
	}
	if _, err := validateVariantPreferences([]string{"chess"}); !errors.Is(err, ErrInvalidProfile) {
		t.Fatalf("unknown err = %v, want ErrInvalidProfile", err)
	}
}
