package main

import (
	"math/rand"
	"testing"
)

func TestUrRollDiceDistribution(t *testing.T) {
	rnd := rand.New(rand.NewSource(1))
	counts := [5]int{}
	for i := 0; i < 10000; i++ {
		counts[urRollDice(rnd)]++
	}
	maxIdx := 0
	for i, c := range counts {
		if c > counts[maxIdx] {
			maxIdx = i
		}
	}
	if maxIdx != 2 {
		t.Errorf("ожидалось, что значение 2 выпадает чаще всего (биномиальное распределение), получено распределение %v", counts)
	}
	if counts[0] == 0 || counts[4] == 0 {
		t.Errorf("значения 0 и 4 должны выпадать хоть иногда (редко, но не нулевая вероятность), получено %v", counts)
	}
}

func playUrFullGame(t *testing.T, g *UrGameState, botA, botB UrBot, rnd *rand.Rand, maxTurns int) {
	t.Helper()
	for turn := 0; turn < maxTurns && g.Result == nil; turn++ {
		var bot UrBot
		if g.CurrentPlayer == UrPlayerA {
			bot = botA
		} else {
			bot = botB
		}
		if err := bot.PlayFullTurn(g, rnd); err != nil {
			t.Fatalf("ход %d: неожиданная ошибка бота: %v", turn, err)
		}
	}
	if g.Result == nil {
		t.Fatalf("партия не завершилась за %d ходов — похоже на зависание", maxTurns)
	}
}

func TestUrBotFullGamesEasyVsEasy(t *testing.T) {
	rnd := rand.New(rand.NewSource(1))
	for i := 0; i < 10; i++ {
		g := NewUrGame(UrPlayerA)
		bot := UrBot{Difficulty: UrDifficultyEasy}
		playUrFullGame(t, g, bot, bot, rnd, 2000)
	}
}

func TestUrBotFullGamesMediumVsMedium(t *testing.T) {
	rnd := rand.New(rand.NewSource(1))
	for i := 0; i < 10; i++ {
		g := NewUrGame(UrPlayerA)
		bot := UrBot{Difficulty: UrDifficultyMedium}
		playUrFullGame(t, g, bot, bot, rnd, 2000)
	}
}

func TestUrBotFullGamesHardVsHard(t *testing.T) {
	rnd := rand.New(rand.NewSource(1))
	for i := 0; i < 5; i++ {
		g := NewUrGame(UrPlayerA)
		bot := UrBot{Difficulty: UrDifficultyHard}
		playUrFullGame(t, g, bot, bot, rnd, 2000)
	}
}

func TestUrBotFullGamesMixedDifficulties(t *testing.T) {
	rnd := rand.New(rand.NewSource(1))
	combos := []struct{ a, b UrDifficulty }{
		{UrDifficultyEasy, UrDifficultyMedium},
		{UrDifficultyMedium, UrDifficultyHard},
		{UrDifficultyEasy, UrDifficultyHard},
	}
	for _, c := range combos {
		g := NewUrGame(UrPlayerA)
		playUrFullGame(t, g, UrBot{Difficulty: c.a}, UrBot{Difficulty: c.b}, rnd, 2000)
	}
}

func TestUrMediumBotPrefersCaptureOverNeutralMove(t *testing.T) {
	rnd := rand.New(rand.NewSource(1))
	g := NewUrGame(UrPlayerA)
	g.Path[UrPlayerA][0] = 4
	g.Path[UrPlayerA][1] = 1
	g.Path[UrPlayerB][0] = 7
	g.CurrentPlayer = UrPlayerA
	g.Rolled = true
	g.DiceValue = 3

	bot := UrBot{Difficulty: UrDifficultyMedium}
	choice := bot.DecideMove(g, rnd)
	if choice != 0 {
		t.Errorf("средний уровень должен был предпочесть взятие шашки соперника, получено индекс %d", choice)
	}
}
