package main

import "testing"

func c(rank Rank, suit Suit) Card {
	return Card{Rank: rank, Suit: suit}
}

func TestIsSet(t *testing.T) {
	valid := []Card{c(Seven, Clubs), c(Seven, Hearts), c(Seven, Spades)}
	if !IsSet(valid) {
		t.Errorf("ожидался валидный сет: %v", valid)
	}

	tooFew := []Card{c(Seven, Clubs), c(Seven, Hearts)}
	if IsSet(tooFew) {
		t.Errorf("сет из 2 карт не должен быть валиден: %v", tooFew)
	}

	mixedRank := []Card{c(Seven, Clubs), c(Eight, Hearts), c(Seven, Spades)}
	if IsSet(mixedRank) {
		t.Errorf("разные ранги не образуют сет: %v", mixedRank)
	}

	dupSuit := []Card{c(Seven, Clubs), c(Seven, Clubs), c(Seven, Hearts)}
	if IsSet(dupSuit) {
		t.Errorf("дублирующиеся масти невалидны: %v", dupSuit)
	}
}

func TestIsSequenceBasic(t *testing.T) {
	run := []Card{c(Five, Hearts), c(Six, Hearts), c(Seven, Hearts)}
	if !IsSequence(run) {
		t.Errorf("ожидался валидный сиквенс: %v", run)
	}

	mixedSuit := []Card{c(Five, Hearts), c(Six, Clubs), c(Seven, Hearts)}
	if IsSequence(mixedSuit) {
		t.Errorf("разные масти не образуют сиквенс: %v", mixedSuit)
	}

	gap := []Card{c(Five, Hearts), c(Seven, Hearts), c(Eight, Hearts)}
	if IsSequence(gap) {
		t.Errorf("сиквенс с пропуском невалиден: %v", gap)
	}
}

func TestIsSequenceAce(t *testing.T) {
	aceLow := []Card{c(Ace, Spades), c(Two, Spades), c(Three, Spades)}
	if !IsSequence(aceLow) {
		t.Errorf("туз снизу должен быть валиден: %v", aceLow)
	}

	aceHigh := []Card{c(Queen, Spades), c(King, Spades), c(Ace, Spades)}
	if !IsSequence(aceHigh) {
		t.Errorf("туз сверху должен быть валиден: %v", aceHigh)
	}

	aceWrap := []Card{c(King, Spades), c(Ace, Spades), c(Two, Spades)}
	if IsSequence(aceWrap) {
		t.Errorf("туз не может замыкать колоду по кругу (K-A-2): %v", aceWrap)
	}
}

func TestFindAllSets(t *testing.T) {
	hand := []Card{
		c(Seven, Clubs), c(Seven, Hearts), c(Seven, Spades),
		c(Nine, Clubs), c(Two, Diamonds),
	}
	sets := FindAllSets(hand)
	if len(sets) != 1 {
		t.Fatalf("ожидался 1 сет, получено %d: %v", len(sets), sets)
	}
	if len(sets[0]) != 3 {
		t.Errorf("ожидалось 3 карты в сете, получено %d", len(sets[0]))
	}
}

func TestFindAllSequences(t *testing.T) {
	hand := []Card{
		c(Four, Hearts), c(Five, Hearts), c(Six, Hearts), c(Seven, Hearts),
		c(Two, Clubs),
	}
	runs := FindAllSequences(hand)
	if len(runs) != 1 {
		t.Fatalf("ожидался 1 сиквенс, получено %d: %v", len(runs), runs)
	}
	if len(runs[0]) != 4 {
		t.Errorf("ожидалась последовательность из 4 карт, получено %d", len(runs[0]))
	}
}

func TestHandValueAndTonk(t *testing.T) {
	hand := []Card{c(Ace, Clubs), c(Two, Hearts), c(King, Spades)}
	// 1 + 2 + 10 = 13
	if v := HandValue(hand); v != 13 {
		t.Errorf("ожидалось значение руки 13, получено %d", v)
	}
	if CanDeclareTonk(hand, 5) {
		t.Errorf("рука с весом 13 не должна позволять Тонк при пороге 5")
	}

	lowHand := []Card{c(Ace, Clubs), c(Two, Hearts)}
	if !CanDeclareTonk(lowHand, 5) {
		t.Errorf("рука с весом 3 должна позволять Тонк при пороге 5")
	}
}

func TestDeckDrawsAllCards(t *testing.T) {
	d := NewDeck()
	if d.Len() != 52 {
		t.Fatalf("ожидалось 52 карты, получено %d", d.Len())
	}
	d.Shuffle()

	seen := make(map[Card]bool)
	for {
		card, ok := d.Draw()
		if !ok {
			break
		}
		if seen[card] {
			t.Fatalf("карта %v встретилась дважды", card)
		}
		seen[card] = true
	}
	if len(seen) != 52 {
		t.Fatalf("ожидалось 52 уникальные карты, получено %d", len(seen))
	}
}
