package com.jsjdesigns.poker

import com.jsjdesigns.poker.game.ActionType
import com.jsjdesigns.poker.game.HandEvent
import com.jsjdesigns.poker.game.Street
import com.jsjdesigns.poker.game.TableSnapshot

enum class TableStatusTone { ACCENT, NORMAL, MUTED }

/** One short, snapshot-derived explanation of what the table is doing now. */
data class TableStatus(val text: String, val tone: TableStatusTone)

/**
 * Turns an immutable engine frame into player-facing status copy.
 *
 * Phase transitions outrank [TableSnapshot.lastAction], because that event is
 * intentionally retained across the next board frame. Without this ordering the
 * freshly dealt flop would still announce the final pre-flop call.
 */
fun tableStatus(
    snapshot: TableSnapshot,
    heroSeat: Int = HERO_SEAT,
): TableStatus? {
    if (snapshot.phase == TableSnapshot.Phase.SHOWDOWN ||
        snapshot.phase == TableSnapshot.Phase.COMPLETE
    ) {
        return null // HandResultBar owns the terminal explanation.
    }

    snapshot.toAct?.let { actingSeat ->
        // Carry the preceding action into the next decision frame so it remains
        // readable for more than the short post-action hold. Restrict it to this
        // street: the first actor on the flop must not resurrect a pre-flop call.
        val previous = snapshot.lastAction
            ?.takeIf { it.street == snapshot.street }
            ?.description(heroSeat)
        return if (actingSeat == heroSeat) {
            TableStatus(
                listOfNotNull("Your turn", previous).joinToString("  •  "),
                TableStatusTone.ACCENT,
            )
        } else {
            val name = snapshot.seats.firstOrNull { it.index == actingSeat }?.name ?: "Player"
            TableStatus(
                listOfNotNull(previous, "$name is thinking…").joinToString("  •  "),
                if (previous == null) TableStatusTone.MUTED else TableStatusTone.NORMAL,
            )
        }
    }

    return when (snapshot.phase) {
        TableSnapshot.Phase.DEALT ->
            TableStatus("Cards dealt", TableStatusTone.NORMAL)
        TableSnapshot.Phase.STREET_COMPLETE ->
            TableStatus("${snapshot.street.displayName()} dealt", TableStatusTone.NORMAL)
        TableSnapshot.Phase.BETTING ->
            snapshot.lastAction?.toStatus(heroSeat)
                ?: TableStatus("Betting", TableStatusTone.MUTED)
        TableSnapshot.Phase.SHOWDOWN,
        TableSnapshot.Phase.COMPLETE,
        -> null
    }
}

private fun HandEvent.toStatus(heroSeat: Int): TableStatus {
    return TableStatus(description(heroSeat), TableStatusTone.NORMAL)
}

private fun HandEvent.description(heroSeat: Int): String {
    val actor = if (seat == heroSeat) "You" else name
    val description = when (action.type) {
        ActionType.FOLD -> "folded"
        ActionType.CHECK -> "checked"
        ActionType.CALL -> "called ${action.amount}"
        ActionType.BET -> "bet ${action.amount}"
        ActionType.RAISE -> "raised to ${action.amount}"
    }
    return "$actor $description"
}

private fun Street.displayName(): String = when (this) {
    Street.PREFLOP -> "Pre-flop"
    Street.FLOP -> "Flop"
    Street.TURN -> "Turn"
    Street.RIVER -> "River"
}
