package app.closer.ui.home

import app.closer.ui.home.HomePriorityEngine.Input
import app.closer.ui.home.HomePriorityEngine.Priority
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test

class HomePriorityEngineTest {

    @Test
    fun `empty input returns pairing as primary because pairing is the default state`() {
        val output = HomePriorityEngine.compute(Input())

        assertEquals(Priority.PAIRING_NEEDED, output.primary?.priority)
        assertEquals(emptyList<Priority>(), output.secondary.map { it.priority })
    }

    @Test
    fun `critical action always wins primary`() {
        val input = Input(
            needsCriticalAction = true,
            revealReady = true,
            dailyQuestionUnanswered = true
        )

        val output = HomePriorityEngine.compute(input)

        assertEquals(Priority.CRITICAL_ACTION, output.primary?.priority)
    }

    @Test
    fun `pairing needed outranks daily question`() {
        val input = Input(
            isPaired = false,
            dailyQuestionUnanswered = true
        )

        val output = HomePriorityEngine.compute(input)

        assertEquals(Priority.PAIRING_NEEDED, output.primary?.priority)
    }

    @Test
    fun `encryption unlock outranks reveal ready`() {
        val input = Input(
            isPaired = true,
            needsEncryptionUnlock = true,
            revealReady = true
        )

        val output = HomePriorityEngine.compute(input)

        assertEquals(Priority.ENCRYPTION_UNLOCK_NEEDED, output.primary?.priority)
    }

    @Test
    fun `reveal ready is primary when no blockers`() {
        val input = Input(
            isPaired = true,
            revealReady = true,
            dailyQuestionUnanswered = true
        )

        val output = HomePriorityEngine.compute(input)

        assertEquals(Priority.REVEAL_READY, output.primary?.priority)
    }

    @Test
    fun `partner answered outranks daily question unanswered`() {
        val input = Input(
            isPaired = true,
            partnerAnsweredUserPending = true,
            dailyQuestionUnanswered = true
        )

        val output = HomePriorityEngine.compute(input)

        assertEquals(Priority.PARTNER_ANSWERED_USER_PENDING, output.primary?.priority)
    }

    @Test
    fun `game waiting outranks challenge waiting`() {
        val input = Input(
            isPaired = true,
            gameWaiting = true,
            challengeWaiting = true
        )

        val output = HomePriorityEngine.compute(input)

        assertEquals(Priority.GAME_WAITING, output.primary?.priority)
    }

    @Test
    fun `challenge waiting outranks daily question`() {
        val input = Input(
            isPaired = true,
            challengeWaiting = true,
            dailyQuestionUnanswered = true
        )

        val output = HomePriorityEngine.compute(input)

        assertEquals(Priority.CHALLENGE_WAITING, output.primary?.priority)
    }

    @Test
    fun `daily question is primary when no higher priority items`() {
        val input = Input(
            isPaired = true,
            dailyQuestionUnanswered = true
        )

        val output = HomePriorityEngine.compute(input)

        assertEquals(Priority.DAILY_QUESTION_UNANSWERED, output.primary?.priority)
    }

    @Test
    fun `weekly recap outranks capsule and date reminder`() {
        val input = Input(
            isPaired = true,
            weeklyRecapReady = true,
            capsuleUnlocked = true,
            dateReminder = true
        )

        val output = HomePriorityEngine.compute(input)

        assertEquals(Priority.WEEKLY_RECAP_READY, output.primary?.priority)
    }

    @Test
    fun `capsule unlocked outranks date reminder`() {
        val input = Input(
            isPaired = true,
            capsuleUnlocked = true,
            dateReminder = true
        )

        val output = HomePriorityEngine.compute(input)

        assertEquals(Priority.CAPSULE_UNLOCKED, output.primary?.priority)
    }

    @Test
    fun `date reminder outranks suggested pack and explore games`() {
        val input = Input(
            isPaired = true,
            dateReminder = true,
            suggestedPackAvailable = true,
            exploreGamesAvailable = true
        )

        val output = HomePriorityEngine.compute(input)

        assertEquals(Priority.DATE_REMINDER, output.primary?.priority)
    }

    @Test
    fun `suggested pack outranks explore games`() {
        val input = Input(
            isPaired = true,
            suggestedPackAvailable = true,
            exploreGamesAvailable = true
        )

        val output = HomePriorityEngine.compute(input)

        assertEquals(Priority.SUGGESTED_PACK, output.primary?.priority)
    }

    @Test
    fun `secondary cards exclude primary`() {
        val input = Input(
            isPaired = true,
            revealReady = true,
            dailyQuestionUnanswered = true,
            weeklyRecapReady = true,
            capsuleUnlocked = true,
            dateReminder = true
        )

        val output = HomePriorityEngine.compute(input)

        assertEquals(Priority.REVEAL_READY, output.primary?.priority)
        assertEquals(
            listOf(
                Priority.DAILY_QUESTION_UNANSWERED,
                Priority.WEEKLY_RECAP_READY,
                Priority.CAPSULE_UNLOCKED
            ),
            output.secondary.map { it.priority }
        )
    }

    @Test
    fun `secondary cards are limited to three and partner triggered first`() {
        val input = Input(
            isPaired = true,
            partnerAnsweredUserPending = true,
            gameWaiting = true,
            challengeWaiting = true,
            dailyQuestionUnanswered = true,
            weeklyRecapReady = true,
            capsuleUnlocked = true
        )

        val output = HomePriorityEngine.compute(input)

        assertEquals(Priority.PARTNER_ANSWERED_USER_PENDING, output.primary?.priority)
        assertEquals(
            listOf(
                Priority.GAME_WAITING,
                Priority.CHALLENGE_WAITING,
                Priority.DAILY_QUESTION_UNANSWERED
            ),
            output.secondary.map { it.priority }
        )
    }

    @Test
    fun `generic browse items do not appear before partner triggered actions`() {
        val input = Input(
            isPaired = true,
            gameWaiting = true,
            dailyQuestionUnanswered = true,
            suggestedPackAvailable = true,
            exploreGamesAvailable = true
        )

        val output = HomePriorityEngine.compute(input)

        assertEquals(
            listOf(Priority.DAILY_QUESTION_UNANSWERED),
            output.secondary.map { it.priority }
        )
    }

    @Test
    fun `primary priority convenience returns pairing needed for default empty input`() {
        assertEquals(Priority.PAIRING_NEEDED, HomePriorityEngine.primaryPriority(Input()))
    }

    @Test
    fun `primary priority convenience returns highest active priority`() {
        val input = Input(
            isPaired = true,
            revealReady = true,
            dailyQuestionUnanswered = true
        )

        assertEquals(Priority.REVEAL_READY, HomePriorityEngine.primaryPriority(input))
    }
}
