package main

import "testing"

// TestOneOhOneBotFullMatches прогоняет много полных матчей (до
// одного оставшегося игрока) силами OneOhOneBot для 2-6 игроков,
// проверяя отсутствие паник, зависаний и потери/дублирования карт.
func TestOneOhOneBotFullMatches(t *testing.T) {
	bot := OneOhOneBot{}

	for numPlayers := 2; numPlayers <= 6; numPlayers++ {
		for match := 0; match < 15; match++ {
			names := make([]string, numPlayers)
			for i := range names {
				names[i] = "Bot"
			}
			g := NewOneOhOneGame(names, -1)

			const maxRounds = 200
			round := 0
			for ; round < maxRounds; round++ {
				const maxSteps = 200000
				steps := 0
				for ; steps < maxSteps && g.Phase != OneOhOnePhaseRoundOver; steps++ {
					if err := bot.PlayFullTurn(g); err != nil {
						t.Fatalf("игроков %d, матч %d, раунд %d, шаг %d: ошибка бота: %v",
							numPlayers, match, round, steps, err)
					}
				}
				if steps >= maxSteps {
					t.Fatalf("игроков %d, матч %d, раунд %d: раунд не завершился за %d шагов",
						numPlayers, match, round, maxSteps)
				}
				if g.Result == nil {
					t.Fatalf("игроков %d, матч %d, раунд %d: раунд завершился без результата",
						numPlayers, match, round)
				}

				// проверка сохранности карт: без дублей и потерь
				seen := map[Card]bool{}
				for _, p := range g.Players {
					for _, c := range p.Hand {
						if seen[c] {
							t.Fatalf("игроков %d, матч %d, раунд %d: карта %v встретилась дважды",
								numPlayers, match, round, c)
						}
						seen[c] = true
					}
				}
				for _, c := range g.Stock {
					if seen[c] {
						t.Fatalf("игроков %d, матч %d, раунд %d: карта %v встретилась дважды (в колоде)",
							numPlayers, match, round, c)
					}
					seen[c] = true
				}
				for _, c := range g.Discard {
					if seen[c] {
						t.Fatalf("игроков %d, матч %d, раунд %d: карта %v встретилась дважды (в сбросе)",
							numPlayers, match, round, c)
					}
					seen[c] = true
				}
				if len(seen) != 36 {
					t.Fatalf("игроков %d, матч %d, раунд %d: ожидалось 36 карт в игре, получено %d",
						numPlayers, match, round, len(seen))
				}

				if g.Result.MatchOver {
					break
				}
				g.NextRound()
			}
			if round >= maxRounds {
				t.Fatalf("игроков %d, матч %d: матч не завершился за %d раундов (возможное зависание)",
					numPlayers, match, maxRounds)
			}
		}
	}
}
