package dev.ulfrx.recipe.ui.screens.recipedetail

import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue

class RecipeDetailViewModelTest {
    @Test
    fun openKnownRecipeShowsFreshState() {
        val viewModel = RecipeDetailViewModel()

        viewModel.open("rcp_nalesniki")

        val state = viewModel.readyState()
        assertEquals("rcp_nalesniki", state.recipe.id)
        assertEquals(MIN_RECIPE_SERVINGS, state.servings)
        assertTrue(state.substitutions.isEmpty())
    }

    @Test
    fun openUnknownRecipeClearsPreviousState() {
        val viewModel = RecipeDetailViewModel()

        viewModel.open("rcp_nalesniki")
        viewModel.open("missing")

        assertEquals(RecipeDetailState.Hidden, viewModel.state.value)
    }

    @Test
    fun servingsAreClampedToSupportedRange() {
        val viewModel = RecipeDetailViewModel()
        viewModel.open("rcp_nalesniki")

        viewModel.setServings(0)
        assertEquals(MIN_RECIPE_SERVINGS, viewModel.readyState().servings)

        viewModel.setServings(MAX_RECIPE_SERVINGS + 1)
        assertEquals(MAX_RECIPE_SERVINGS, viewModel.readyState().servings)
    }

    @Test
    fun substitutionCanBeSelectedAndResetToDefault() {
        val viewModel = RecipeDetailViewModel()
        viewModel.open("rcp_nalesniki")
        val slot =
            viewModel
                .readyState()
                .recipe.ingredients
                .first { it.alternatives.isNotEmpty() }
        val alternative = slot.alternatives.first()

        viewModel.selectSubstitution(slot.id, alternative.id)
        assertEquals(alternative.id, viewModel.readyState().substitutions[slot.id])

        viewModel.selectSubstitution(slot.id, slot.default.id)
        assertFalse(slot.id in viewModel.readyState().substitutions)
    }

    @Test
    fun invalidSubstitutionIsIgnored() {
        val viewModel = RecipeDetailViewModel()
        viewModel.open("rcp_nalesniki")
        val slot =
            viewModel
                .readyState()
                .recipe.ingredients
                .first { it.alternatives.isNotEmpty() }

        viewModel.selectSubstitution(slot.id, "missing")

        assertTrue(viewModel.readyState().substitutions.isEmpty())
    }

    private fun RecipeDetailViewModel.readyState(): RecipeDetailState.Ready {
        val state = state.value
        assertTrue(state is RecipeDetailState.Ready)
        return state
    }
}
