package ws

import "hakemsho/internal/game"

// هوشِ باتِ حکم — تصمیم‌گیریِ اکتشافی (heuristic) که فقط از دستِ خودِ بات و
// کارت‌های روی زمین استفاده می‌کند (بدونِ دیدنِ دستِ دیگران؛ بازیِ منصفانه).
//
// راهبردها:
//   - انتخابِ حکم: خالی که هم بلند است و هم کارتِ قوی دارد.
//   - رهبریِ دست: آسِ غیرِحکم را نقد کن؛ وگرنه از بلندترین خالِ غیرِحکم کارتِ کم بریز.
//   - دنبال‌کردن: اگر شریک می‌برد کارتِ کم بریز؛ اگر حریف می‌برد با کمترین کارتِ
//     برنده ببر؛ اگر خالِ زمینه را نداری و حریف می‌برد با کمترین حکم بِبُر.

// botChooseTrump خالِ حکم را بر اساسِ طول + قدرتِ کارت‌ها انتخاب می‌کند.
func botChooseTrump(hand []game.Card) game.Suit {
	var score [4]float64
	for _, c := range hand {
		score[c.Suit] += 1
		switch c.Rank {
		case game.Ace:
			score[c.Suit] += 2.0
		case game.King:
			score[c.Suit] += 1.3
		case game.Queen:
			score[c.Suit] += 0.7
		case game.Jack:
			score[c.Suit] += 0.3
		}
	}
	best, bestScore := game.Suit(0), -1.0
	for s := game.Suit(0); s < 4; s++ {
		if score[s] > bestScore {
			bestScore, best = score[s], s
		}
	}
	return best
}

// botPlay کارتی که بات باید بازی کند را برمی‌گرداند.
func botPlay(hand []game.Card, trick []game.TrickCard, trump, lead game.Suit) game.Card {
	if len(trick) == 0 {
		return botLead(hand, trump)
	}

	best := trickBest(trick, trump, lead)
	// جایگاه‌ها متناوب‌اند؛ کارتی که دو نوبت قبل انداخته شده متعلق به شریکِ باتِ
	// در نوبت است. اگر آن (یا هر کارتِ شریک) بهترین کارتِ فعلی باشد، شریک می‌برد.
	partnerWins := false
	if len(trick) >= 2 {
		partnerWins = best.Seat == trick[len(trick)-2].Seat
	}

	followers := cardsOfSuit(hand, lead)
	if len(followers) > 0 {
		if partnerWins {
			return lowest(followers) // شریک می‌برد ⇒ کارتِ کم بریز
		}
		if w, ok := lowestWinner(followers, best.Card, trump, lead); ok {
			return w // با کمترین کارتِ برنده ببر
		}
		return lowest(followers) // نمی‌توانی ببری ⇒ کارتِ کم
	}

	// خالِ زمینه را نداریم (void).
	trumps := cardsOfSuit(hand, trump)
	if partnerWins || len(trumps) == 0 {
		return lowestDiscard(hand, trump)
	}
	if w, ok := lowestWinner(trumps, best.Card, trump, lead); ok {
		return w // با کمترین حکمِ برنده بِبُر
	}
	return lowestDiscard(hand, trump) // حکمت هم نمی‌برد ⇒ دورریز
}

// botLead راهبردِ رهبریِ دست: آسِ غیرِحکم را نقد کن؛ وگرنه از بلندترین خالِ
// غیرِحکم کارتِ کم بریز؛ اگر فقط حکم داری، بالاترین حکم را بزن تا حکم‌ها را بکشی.
func botLead(hand []game.Card, trump game.Suit) game.Card {
	// آسِ غیرِحکم (برنده‌ی تقریباً قطعی).
	var ace *game.Card
	for i := range hand {
		if hand[i].Suit != trump && hand[i].Rank == game.Ace {
			c := hand[i]
			ace = &c
			break
		}
	}
	if ace != nil {
		return *ace
	}

	// بلندترین خالِ غیرِحکم.
	var counts [4]int
	for _, c := range hand {
		counts[c.Suit]++
	}
	bestSuit, bestLen := game.Suit(255), -1
	for _, c := range hand {
		if c.Suit == trump {
			continue
		}
		if counts[c.Suit] > bestLen {
			bestLen, bestSuit = counts[c.Suit], c.Suit
		}
	}
	if bestSuit != game.Suit(255) {
		return lowest(cardsOfSuit(hand, bestSuit))
	}
	// فقط حکم مانده ⇒ بالاترین حکم را بزن.
	return highest(cardsOfSuit(hand, trump))
}

// --- کمکی‌ها ---

func trickBest(trick []game.TrickCard, trump, lead game.Suit) game.TrickCard {
	best := trick[0]
	for _, tc := range trick[1:] {
		if game.Beats(tc.Card, best.Card, trump, lead) {
			best = tc
		}
	}
	return best
}

func cardsOfSuit(hand []game.Card, s game.Suit) []game.Card {
	var out []game.Card
	for _, c := range hand {
		if c.Suit == s {
			out = append(out, c)
		}
	}
	return out
}

func lowest(cards []game.Card) game.Card {
	best := cards[0]
	for _, c := range cards[1:] {
		if c.Rank < best.Rank {
			best = c
		}
	}
	return best
}

func highest(cards []game.Card) game.Card {
	best := cards[0]
	for _, c := range cards[1:] {
		if c.Rank > best.Rank {
			best = c
		}
	}
	return best
}

// lowestWinner کمترین کارتِ candidate که کارتِ فعلیِ برنده را می‌برد.
func lowestWinner(candidates []game.Card, cur game.Card, trump, lead game.Suit) (game.Card, bool) {
	var best game.Card
	found := false
	for _, c := range candidates {
		if game.Beats(c, cur, trump, lead) && (!found || c.Rank < best.Rank) {
			best, found = c, true
		}
	}
	return best, found
}

// lowestDiscard کمترین کارتِ غیرِحکم را برای دورریز برمی‌گرداند؛ اگر فقط حکم مانده،
// کمترین حکم.
func lowestDiscard(hand []game.Card, trump game.Suit) game.Card {
	var nonTrump []game.Card
	for _, c := range hand {
		if c.Suit != trump {
			nonTrump = append(nonTrump, c)
		}
	}
	if len(nonTrump) > 0 {
		return lowest(nonTrump)
	}
	return lowest(hand)
}
