package account

import (
	"slices"
	"testing"
)

// TestSeedVariantsFromStartParam covers decoding a promo deep-link start-param into the
// variant-preference set to seed: a valid "v"-prefixed, "-"-joined label list is cleaned
// to the canonical order and deduplicated, while anything that is not a variant-seed link
// or that names an unknown variant yields nil (leaving the account on its defaults).
func TestSeedVariantsFromStartParam(t *testing.T) {
	tests := []struct {
		name  string
		param string
		want  []string
	}{
		{"english promo", "verudit_ru-scrabble_en", []string{"erudit_ru", "scrabble_en"}},
		{"single variant", "vscrabble_en", []string{"scrabble_en"}},
		{"canonical order regardless of payload order", "vscrabble_en-erudit_ru", []string{"erudit_ru", "scrabble_en"}},
		{"deduplicated", "verudit_ru-erudit_ru", []string{"erudit_ru"}},
		{"empty", "", nil},
		{"prefix only", "v", nil},
		{"routing game link is not a seed", "g0190abcd", nil},
		{"friend code link is not a seed", "f123456", nil},
		{"unknown variant rejected", "vscrabble_de", nil},
		{"one unknown label rejects the whole set", "verudit_ru-scrabble_de", nil},
	}
	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			got := SeedVariantsFromStartParam(tc.param)
			if !slices.Equal(got, tc.want) {
				t.Errorf("SeedVariantsFromStartParam(%q) = %v, want %v", tc.param, got, tc.want)
			}
		})
	}
}

// TestMergeVariantSeed covers resolving what a promo-onboarded account should end up with:
// the seed only ever widens the current set, English Scrabble is withheld from a
// Russian-speaking arrival, and a merge that changes nothing reports nil so the caller
// skips the write.
func TestMergeVariantSeed(t *testing.T) {
	promo := []string{"erudit_ru", "scrabble_en"} // the campaign link "verudit_ru-scrabble_en"
	tests := []struct {
		name     string
		current  []string
		seed     []string
		language string
		want     []string
	}{
		{"russian speaker keeps the default", DefaultVariantPreferences, promo, "ru", nil},
		{"russian locale variant is still russian", DefaultVariantPreferences, promo, "ru-RU", nil},
		{"english speaker gains english", DefaultVariantPreferences, promo, "en", []string{"erudit_ru", "scrabble_ru", "scrabble_en"}},
		{"unsupported language is not russian", DefaultVariantPreferences, promo, "de", []string{"erudit_ru", "scrabble_ru", "scrabble_en"}},
		{"absent language is not russian", DefaultVariantPreferences, promo, "", []string{"erudit_ru", "scrabble_ru", "scrabble_en"}},
		{"no seed writes nothing", DefaultVariantPreferences, nil, "en", nil},
		{"seed already covered writes nothing", DefaultVariantPreferences, []string{"scrabble_ru"}, "ru", nil},
		{"the russian filter spares the account's own english", []string{"erudit_ru", "scrabble_en"}, promo, "ru", nil},
		{"invalid seed writes nothing", DefaultVariantPreferences, []string{"chess"}, "en", nil},
		{"a guest set is widened by the seed", GuestVariantPreferences, []string{"scrabble_ru"}, "ru", DefaultVariantPreferences},
	}
	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			got := MergeVariantSeed(tc.current, tc.seed, tc.language)
			if !slices.Equal(got, tc.want) {
				t.Errorf("MergeVariantSeed(%v, %v, %q) = %v, want %v", tc.current, tc.seed, tc.language, got, tc.want)
			}
		})
	}
}
