package com.jsjdesigns.poker

import com.jsjdesigns.poker.bot.CoachingReview
import com.jsjdesigns.poker.bot.DecisionTrace
import com.jsjdesigns.poker.game.Action
import com.jsjdesigns.poker.game.ActionType
import com.jsjdesigns.poker.game.Street
import com.jsjdesigns.poker.game.TableSnapshot
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test

class CoachPresentationTest {

    private fun review(
        handNumber: Int = 4,
        token: Long = 12,
        street: Street = Street.RIVER,
        aligned: Boolean = false,
        trace: DecisionTrace = postflopTrace(),
    ) = CoachingReview(
        decisionToken = token,
        handNumber = handNumber,
        street = street,
        trace = trace,
        alignedWithBaseline = aligned,
    )

    @Test
    fun `postflop presentation consumes audited equity and pot odds fields`() {
        val presentation = coachPresentation(review())

        assertEquals("Worth reviewing", presentation.title)
        assertEquals(
            "Estimated 34% equity vs random hands; calling needs 25%. Baseline: Call 20.",
            presentation.detail,
        )
    }

    @Test
    fun `preflop presentation never describes percentile as equity`() {
        val trace = DecisionTrace(
            estimatedEquity = null,
            handStrengthPercentile = 0.08,
            breakEvenEquity = null,
            decisionThreshold = null,
            preflopRangeThreshold = 0.22,
            potOdds = null,
            intended = Action(ActionType.RAISE, 6),
            chosen = Action(ActionType.RAISE, 8),
            mistakeApplied = false,
            adjustments = emptyList(),
            reason = "chart baseline",
        )

        val presentation = coachPresentation(
            review(street = Street.PREFLOP, aligned = true, trace = trace),
        )

        assertEquals("Baseline agrees", presentation.title)
        assertTrue("percentile" in presentation.detail)
        assertTrue("equity" !in presentation.detail)
        assertTrue("Raise to 6" in presentation.detail)
    }

    @Test
    fun `review is visible only for opted-in exact latest decision and hand`() {
        val review = review()
        val matching = UiState(
            gameConfig = CashGameConfig("Jay", coachEnabled = true),
            snapshot = snapshot(handNumber = 4),
            coachReview = review,
            latestHeroDecisionToken = 12,
        )

        assertEquals(review, matching.visibleCoachReview())
        assertNull(
            matching.copy(
                gameConfig = matching.gameConfig?.copy(coachEnabled = false),
            ).visibleCoachReview(),
        )
        assertNull(matching.copy(latestHeroDecisionToken = 13).visibleCoachReview())
        assertNull(matching.copy(snapshot = snapshot(handNumber = 5)).visibleCoachReview())
    }

    private fun postflopTrace() = DecisionTrace(
        estimatedEquity = 0.34,
        handStrengthPercentile = null,
        breakEvenEquity = 0.25,
        decisionThreshold = 0.25,
        preflopRangeThreshold = null,
        potOdds = "60:20",
        intended = Action(ActionType.CALL, 20),
        chosen = Action(ActionType.FOLD),
        mistakeApplied = false,
        adjustments = emptyList(),
        reason = "fundamentals baseline",
    )

    private fun snapshot(handNumber: Int) = TableSnapshot(
        handNumber = handNumber,
        street = Street.RIVER,
        phase = TableSnapshot.Phase.BETTING,
        board = emptyList(),
        pot = 80,
        currentBet = 20,
        minRaiseSize = 20,
        button = 0,
        seats = emptyList(),
        toAct = null,
        toActToken = null,
        lastAction = null,
    )
}
