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

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.BasicText
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import dev.ulfrx.recipe.ui.components.recipe.IngredientCard
import dev.ulfrx.recipe.ui.components.recipe.IngredientDivider
import dev.ulfrx.recipe.ui.components.recipe.IngredientRow
import dev.ulfrx.recipe.ui.components.recipe.RecipeIngredientSlotUi
import dev.ulfrx.recipe.ui.components.recipe.RecipeNutritionUi
import dev.ulfrx.recipe.ui.components.recipe.RecipeServingsStepper
import dev.ulfrx.recipe.ui.components.recipe.NutritionSummary
import dev.ulfrx.recipe.ui.components.recipe.scaledBy
import dev.ulfrx.recipe.ui.components.section.Section
import dev.ulfrx.recipe.ui.components.section.SectionTitle
import dev.ulfrx.recipe.ui.theme.RecipeTheme
import org.jetbrains.compose.resources.stringResource
import recipe.composeapp.generated.resources.Res
import recipe.composeapp.generated.resources.nutrition_label
import recipe.composeapp.generated.resources.recipe_detail_section_ingredients
import recipe.composeapp.generated.resources.recipe_detail_section_steps
import recipe.composeapp.generated.resources.recipe_detail_servings_decrement_a11y
import recipe.composeapp.generated.resources.recipe_detail_servings_increment_a11y
import recipe.composeapp.generated.resources.recipe_detail_servings_label
import recipe.composeapp.generated.resources.recipe_detail_step_number_format

@Composable
internal fun RecipeDetailContent(
    ready: RecipeDetailState.Ready,
    onServingsChange: (Int) -> Unit,
    onSelectSubstitution: (slotId: String, optionId: String) -> Unit,
    topChromeInset: Dp,
    topChromeHeight: Dp,
    modifier: Modifier = Modifier,
) {
    val spacing = RecipeTheme.spacing
    val scrollState = rememberScrollState()
    val bottomInset = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding()

    val detail = ready.recipe
    val servings = ready.servings

    Column(modifier = modifier.fillMaxSize().verticalScroll(scrollState)) {
        Spacer(Modifier.height(topChromeInset))
        // Aligns the title row with the floating close chrome at scroll=0:
        // same height, padded inside the chrome's circle pill.
        Box(
            modifier =
                Modifier
                    .fillMaxWidth()
                    .height(topChromeHeight)
                    .padding(horizontal = spacing.lg + topChromeHeight + spacing.sm),
            contentAlignment = Alignment.Center,
        ) {
            BasicText(
                text = detail.title,
                maxLines = 1,
                overflow = TextOverflow.Ellipsis,
                style =
                    RecipeTheme.typography.body.copy(
                        color = RecipeTheme.colors.content,
                        fontWeight = FontWeight.Medium,
                        fontSize = TitleSize,
                        lineHeight = TitleLineHeight,
                        textAlign = TextAlign.Center,
                    ),
                modifier = Modifier.fillMaxWidth(),
            )
        }
        Spacer(Modifier.height(spacing.xl))

        RecipeDetailHero(cookingMinutes = detail.cookingMinutes)

        Column(modifier = Modifier.fillMaxWidth().padding(horizontal = spacing.lg)) {
            Spacer(Modifier.height(spacing.xl))
            NutritionSection(nutrition = detail.nutrition.scaledBy(servings))

            Spacer(Modifier.height(spacing.xl))
            ServingsSection(servings = servings, onServingsChange = onServingsChange)

            Spacer(Modifier.height(spacing.xl))
            IngredientsSection(
                ingredients = detail.ingredients,
                servings = servings,
                substitutions = ready.substitutions,
                onSelectSubstitution = onSelectSubstitution,
            )

            Spacer(Modifier.height(spacing.xl))
            StepsSection(steps = detail.steps)

            Spacer(Modifier.height(bottomInset + spacing.xxl))
        }
    }
}

@Composable
private fun NutritionSection(nutrition: RecipeNutritionUi) {
    Section(title = stringResource(Res.string.nutrition_label)) {
        NutritionSummary(nutrition = nutrition)
    }
}

@Composable
private fun ServingsSection(
    servings: Int,
    onServingsChange: (Int) -> Unit,
) {
    Row(
        modifier = Modifier.fillMaxWidth(),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween,
    ) {
        SectionTitle(text = stringResource(Res.string.recipe_detail_servings_label))
        RecipeServingsStepper(
            servings = servings,
            servingsRange = MIN_RECIPE_SERVINGS..MAX_RECIPE_SERVINGS,
            decrementContentDescription = stringResource(Res.string.recipe_detail_servings_decrement_a11y),
            incrementContentDescription = stringResource(Res.string.recipe_detail_servings_increment_a11y),
            onServingsChange = onServingsChange,
        )
    }
}

@Composable
private fun IngredientsSection(
    ingredients: List<RecipeIngredientSlotUi>,
    servings: Int,
    substitutions: Map<String, String>,
    onSelectSubstitution: (slotId: String, optionId: String) -> Unit,
) {
    Section(title = stringResource(Res.string.recipe_detail_section_ingredients)) {
        IngredientCard {
            ingredients.forEachIndexed { index, slot ->
                if (index > 0) IngredientDivider()
                IngredientRow(
                    slot = slot.scaledBy(servings),
                    selectedOptionId = substitutions[slot.id] ?: slot.default.id,
                    onSelect =
                        if (slot.alternatives.isNotEmpty()) {
                            { choice -> onSelectSubstitution(slot.id, choice.id) }
                        } else {
                            null
                        },
                )
            }
        }
    }
}

@Composable
private fun StepsSection(steps: List<String>) {
    Section(title = stringResource(Res.string.recipe_detail_section_steps)) {
        Column(verticalArrangement = Arrangement.spacedBy(RecipeTheme.spacing.sm)) {
            steps.forEachIndexed { index, step ->
                StepRow(number = index + 1, text = step)
            }
        }
    }
}

@Composable
private fun StepRow(
    number: Int,
    text: String,
) {
    val colors = RecipeTheme.colors
    Row(horizontalArrangement = Arrangement.spacedBy(RecipeTheme.spacing.sm)) {
        BasicText(
            text = stringResource(Res.string.recipe_detail_step_number_format, number),
            style =
                RecipeTheme.typography.body.copy(
                    color = colors.contentMuted,
                    fontWeight = FontWeight.Bold,
                    fontSize = StepNumberTextSize,
                ),
            modifier = Modifier.width(StepNumberWidth),
        )
        BasicText(
            text = text,
            style =
                RecipeTheme.typography.body.copy(
                    color = colors.content,
                    fontWeight = FontWeight.Normal,
                    fontSize = StepTextSize,
                    lineHeight = StepLineHeight,
                ),
            modifier = Modifier.weight(1f),
        )
    }
}

private val TitleSize = 16.sp
private val TitleLineHeight = 17.sp

private val StepNumberWidth = 20.dp
private val StepNumberTextSize = 11.sp
private val StepTextSize = 13.sp
private val StepLineHeight = 19.sp
