package com.jsjdesigns.poker.core

enum class Suit(val symbol: Char, val assetName: String) {
    CLUBS('c', "clubs"),
    DIAMONDS('d', "diamonds"),
    HEARTS('h', "hearts"),
    SPADES('s', "spades");

    val isRed: Boolean get() = this == DIAMONDS || this == HEARTS
}

/**
 * A card as a single Int in 0..51.
 *
 * Encoding is `(rank - 2) * 4 + suit.ordinal`, which keeps ranks contiguous so the
 * evaluator can bucket by rank with plain array indexing and no branching.
 * Ranks run 2..14 with 14 = ace.
 */
@JvmInline
value class Card(val index: Int) {

    val rank: Int get() = 2 + index / 4
    val suit: Suit get() = Suit.entries[index % 4]

    /** Filename in `assets/cards/`, e.g. `ace_of_spades.svg`. */
    val assetName: String get() = "${rankAssetName(rank)}_of_${suit.assetName}.svg"

    /** Compact form used in logs and tests, e.g. `Ah`, `Td`, `2c`. */
    override fun toString(): String = "${rankSymbol(rank)}${suit.symbol}"

    companion object {
        const val DECK_SIZE = 52

        fun of(rank: Int, suit: Suit): Card {
            require(rank in 2..14) { "rank out of range: $rank" }
            return Card((rank - 2) * 4 + suit.ordinal)
        }

        /** Parses `Ah`, `td`, `10c`, `2S`. */
        fun parse(text: String): Card {
            val s = text.trim()
            require(s.length >= 2) { "unparseable card: '$text'" }
            val suitChar = s.last().lowercaseChar()
            val suit = Suit.entries.firstOrNull { it.symbol == suitChar }
                ?: throw IllegalArgumentException("unknown suit in '$text'")
            val rankPart = s.dropLast(1)
            val rank = when (rankPart.uppercase()) {
                "A" -> 14
                "K" -> 13
                "Q" -> 12
                "J" -> 11
                "T", "10" -> 10
                else -> rankPart.toIntOrNull()
                    ?: throw IllegalArgumentException("unknown rank in '$text'")
            }
            return of(rank, suit)
        }

        fun rankSymbol(rank: Int): String = when (rank) {
            14 -> "A"; 13 -> "K"; 12 -> "Q"; 11 -> "J"; 10 -> "T"
            else -> rank.toString()
        }

        fun rankAssetName(rank: Int): String = when (rank) {
            14 -> "ace"; 13 -> "king"; 12 -> "queen"; 11 -> "jack"
            else -> rank.toString()
        }
    }
}

/** Parses a space-separated list such as `"Ah Kd 7c"`. */
fun cardsOf(text: String): IntArray =
    text.split(' ', ',').filter { it.isNotBlank() }.map { Card.parse(it).index }.toIntArray()

fun IntArray.cardsToString(): String = joinToString(" ") { Card(it).toString() }
