package game

import (
	"crypto/rand"
	"fmt"
	"math/big"
	"strings"
)

// Suit خال کارت.
type Suit uint8

const (
	Spades Suit = iota
	Hearts
	Diamonds
	Clubs
)

var suitChar = [4]byte{'S', 'H', 'D', 'C'}
var suitName = [4]string{"spades", "hearts", "diamonds", "clubs"}

func (s Suit) String() string { return suitName[s] }

// ParseSuit نام انگلیسی خال را به Suit تبدیل می‌کند.
func ParseSuit(name string) (Suit, error) {
	switch strings.ToLower(name) {
	case "spades", "s":
		return Spades, nil
	case "hearts", "h":
		return Hearts, nil
	case "diamonds", "d":
		return Diamonds, nil
	case "clubs", "c":
		return Clubs, nil
	}
	return 0, fmt.Errorf("invalid suit: %q", name)
}

// Rank ارزش کارت؛ 2..10 معمولی، 11=J 12=Q 13=K 14=A.
type Rank uint8

const (
	Jack  Rank = 11
	Queen Rank = 12
	King  Rank = 13
	Ace   Rank = 14
)

// Card یک کارت بازی.
type Card struct {
	Suit Suit
	Rank Rank
}

// String کد کوتاه کارت مثل "AS", "10H", "2C".
func (c Card) String() string {
	var r string
	switch c.Rank {
	case Ace:
		r = "A"
	case King:
		r = "K"
	case Queen:
		r = "Q"
	case Jack:
		r = "J"
	default:
		r = fmt.Sprintf("%d", c.Rank)
	}
	return r + string(suitChar[c.Suit])
}

// ParseCard کد کوتاه کارت را پارس می‌کند (مثلاً "10H", "AS").
func ParseCard(code string) (Card, error) {
	code = strings.ToUpper(strings.TrimSpace(code))
	if len(code) < 2 {
		return Card{}, fmt.Errorf("invalid card: %q", code)
	}
	rankStr := code[:len(code)-1]
	suitStr := code[len(code)-1:]

	s, err := ParseSuit(suitStr)
	if err != nil {
		return Card{}, fmt.Errorf("invalid card %q: %w", code, err)
	}

	var r Rank
	switch rankStr {
	case "A":
		r = Ace
	case "K":
		r = King
	case "Q":
		r = Queen
	case "J":
		r = Jack
	default:
		var n int
		if _, err := fmt.Sscanf(rankStr, "%d", &n); err != nil || n < 2 || n > 10 {
			return Card{}, fmt.Errorf("invalid rank in card %q", code)
		}
		r = Rank(n)
	}
	return Card{Suit: s, Rank: r}, nil
}

// NewDeck یک دسته ۵۲ کارتی مرتب می‌سازد.
func NewDeck() []Card {
	deck := make([]Card, 0, 52)
	for s := Suit(0); s < 4; s++ {
		for r := Rank(2); r <= Ace; r++ {
			deck = append(deck, Card{Suit: s, Rank: r})
		}
	}
	return deck
}

// Shuffle دسته را با crypto/rand به‌صورت Fisher-Yates بُر می‌زند.
func Shuffle(deck []Card) {
	for i := len(deck) - 1; i > 0; i-- {
		jBig, err := rand.Int(rand.Reader, big.NewInt(int64(i+1)))
		if err != nil {
			continue // عملاً رخ نمی‌دهد
		}
		j := int(jBig.Int64())
		deck[i], deck[j] = deck[j], deck[i]
	}
}
