package app.closer.ui.home

/**
 * Pure logic that decides what to show on the home screen based on user state.
 *
 * The engine has no Android dependencies and no side effects. It takes a snapshot
 * of flags and emits a prioritized list of actions: one primary CTA and up to three
 * secondary cards.
 *
 * Priority order (highest to lowest):
 * 1. Critical privacy or account action
 * 2. Pairing needed
 * 3. Encryption unlock needed
 * 4. Reveal ready
 * 5. Partner answered, user pending
 * 6. Game waiting
 * 7. Challenge waiting
 * 8. Daily question unanswered
 * 9. Weekly recap ready
 * 10. Capsule unlocked
 * 11. Date reminder
 * 12. Suggested pack
 * 13. Explore games
 *
 * Rules:
 * - Show one primary CTA.
 * - Show up to 3 secondary cards.
 * - Do not show paywall before core value is experienced.
 * - Do not show generic content above partner-triggered actions.
 * - Partner-triggered items outrank generic browse items.
 */
object HomePriorityEngine {

    /**
     * Input snapshot for the engine. All fields are simple values so callers can
     * build it from any source (ViewModel, tests, previews) without dependencies.
     */
    data class Input(
        val needsCriticalAction: Boolean = false,
        val isPaired: Boolean = false,
        val needsEncryptionUnlock: Boolean = false,
        val revealReady: Boolean = false,
        val partnerAnsweredUserPending: Boolean = false,
        val gameWaiting: Boolean = false,
        val challengeWaiting: Boolean = false,
        val dailyQuestionUnanswered: Boolean = false,
        val weeklyRecapReady: Boolean = false,
        val capsuleUnlocked: Boolean = false,
        val dateReminder: Boolean = false,
        val suggestedPackAvailable: Boolean = false,
        val exploreGamesAvailable: Boolean = false
    )

    enum class Priority {
        CRITICAL_ACTION,
        PAIRING_NEEDED,
        ENCRYPTION_UNLOCK_NEEDED,
        REVEAL_READY,
        PARTNER_ANSWERED_USER_PENDING,
        GAME_WAITING,
        CHALLENGE_WAITING,
        DAILY_QUESTION_UNANSWERED,
        WEEKLY_RECAP_READY,
        CAPSULE_UNLOCKED,
        DATE_REMINDER,
        SUGGESTED_PACK,
        EXPLORE_GAMES
    }

    /**
     * A single prioritized action emitted by the engine.
     *
     * @param priority The engine priority. Lower ordinal = higher rank.
     * @param isPrimary True when this item should be the main CTA.
     */
    data class PrioritizedAction(
        val priority: Priority,
        val isPrimary: Boolean
    )

    /**
     * Engine output: exactly one primary action and up to [maxSecondary] secondary cards.
     */
    data class Output(
        val primary: PrioritizedAction?,
        val secondary: List<PrioritizedAction>
    )

    private const val MAX_SECONDARY = 3

    private val priorityOrder = Priority.entries.toList()

    /**
     * Compute the home screen priority from the given [input].
     *
     * @return An [Output] containing one primary action and up to 3 secondary actions.
     */
    fun compute(input: Input): Output {
        val active = priorityOrder.filter { it.isActive(input) }

        if (active.isEmpty()) {
            return Output(primary = null, secondary = emptyList())
        }

        val primary = active.first()
        val secondary = active
            .drop(1)
            .filter { it.isPartnerTriggered() || it.isValueAction() }
            .take(MAX_SECONDARY)

        return Output(
            primary = PrioritizedAction(priority = primary, isPrimary = true),
            secondary = secondary.map { PrioritizedAction(priority = it, isPrimary = false) }
        )
    }

    /**
     * Convenience overload that returns the primary priority directly, or null
     * when nothing is active.
     */
    fun primaryPriority(input: Input): Priority? = compute(input).primary?.priority

    private fun Priority.isActive(input: Input): Boolean = when (this) {
        Priority.CRITICAL_ACTION -> input.needsCriticalAction
        Priority.PAIRING_NEEDED -> !input.isPaired
        Priority.ENCRYPTION_UNLOCK_NEEDED -> input.needsEncryptionUnlock
        Priority.REVEAL_READY -> input.revealReady
        Priority.PARTNER_ANSWERED_USER_PENDING -> input.partnerAnsweredUserPending
        Priority.GAME_WAITING -> input.gameWaiting
        Priority.CHALLENGE_WAITING -> input.challengeWaiting
        Priority.DAILY_QUESTION_UNANSWERED -> input.dailyQuestionUnanswered
        Priority.WEEKLY_RECAP_READY -> input.weeklyRecapReady
        Priority.CAPSULE_UNLOCKED -> input.capsuleUnlocked
        Priority.DATE_REMINDER -> input.dateReminder
        Priority.SUGGESTED_PACK -> input.suggestedPackAvailable
        Priority.EXPLORE_GAMES -> input.exploreGamesAvailable
    }

    /**
     * Partner-triggered actions are items that should appear before generic browse
     * content because they respond to something the partner did.
     */
    private fun Priority.isPartnerTriggered(): Boolean = when (this) {
        Priority.REVEAL_READY,
        Priority.PARTNER_ANSWERED_USER_PENDING,
        Priority.GAME_WAITING,
        Priority.CHALLENGE_WAITING,
        Priority.CAPSULE_UNLOCKED -> true
        else -> false
    }

    /**
     * Value actions are non-generic content that keeps the daily ritual moving.
     */
    private fun Priority.isValueAction(): Boolean = when (this) {
        Priority.DAILY_QUESTION_UNANSWERED,
        Priority.WEEKLY_RECAP_READY,
        Priority.DATE_REMINDER -> true
        else -> false
    }
}
