import {useParams} from "react-router-dom"
import type {RecipeModel} from "../../models/RecipeModel"
import {useEffect, useState} from "react"
import {fetchRecipe} from "../../api/points/RecipePoint"
import {getRecipeEditUrl, getRecipeListUrl} from "../../routes"
import ButtonLink from "../basics/ButtonLink"
import {mapRecipeDtoToModel} from "../../mappers/RecipeMapper"
import {NumberStepControl} from "../basics/NumberStepControl.tsx";
import {NumberedListItem} from "../basics/NumberedListItem.tsx";
import {ButtonType} from "../basics/BasicButtonDefinitions.ts";


/**
 * Displays the full detail of a single recipe,
 * including its ingredients, instructions, and image.
 */
export default function RecipeDetailPage() {
    // Extract recipe ID from route params
    const {id} = useParams<{ id: string }>()
    // the recipe loaded from the backend, don't change this! it's required for scaling
    const [recipe, setRecipe] = useState<RecipeModel | null>(null)
    // Working copy for re-calculating ingredients
    const [recipeWorkingCopy, setRecipeWorkingCopy] = useState<RecipeModel | null>(null)
    // load recipe data whenever id changes
    useEffect(() => {
        const loadRecipe = async () => {
            if (id) {
                // Fetch recipe data when editing an existing one
                console.log("loading recipe with id", id)
                const data = await fetchRecipe(id)
                if (data.id != id) {
                    throw new Error("Id mismatch when loading recipes: " + id + " requested and " + data.id + " received!");
                }
                setRecipe(mapRecipeDtoToModel(data))
            }
        }

        loadRecipe()
    }, [id])

    // set original recipe data and working copy when recipe changes
    useEffect(() => {
        setRecipeWorkingCopy(recipe);
    }, [recipe])


    if (!recipe || !recipeWorkingCopy) {
        return <p className="p-6">Recipe not found.</p>
    }


    /** recalculate ingredients based on the amount of servings */
    const recalculateIngredients = (newAmount: number) => {
        // Always calculate factor from the *original recipe*, not the working copy
        const factor = newAmount / recipe.servings.amount

        // Create a new ingredient list with updated amounts
        const updatedIngredientGroupList = recipe.ingredientGroupList.map((ingGrp) => ({
            ...ingGrp,
            ingredientList: ingGrp.ingredientList.map((ing) => ({
                ...ing,
                // ensure only to recalculate the amount of ingredients that actually have an amout...
                amount: (ing.amount) ? ing.amount * factor : undefined,
            }))
        }))

        // Update working copy with new servings + recalculated ingredients
        setRecipeWorkingCopy({
            ...recipeWorkingCopy,
            servings: {
                ...recipeWorkingCopy.servings,
                amount: newAmount,
            },
            ingredientGroupList: updatedIngredientGroupList,
        })
    }

    return (
        /*Container spanning entire screen used to center content horizontally */
        <div className="app-bg">
            {/* Container defining the maximum width of the content */}
            <div className="content-bg">
                {/* Header - remains in position when scrolling */}
                <div className="sticky-header">
                    <h1>{recipeWorkingCopy.title}</h1>
                </div>

                {/* Content */}
                <div className="content-container">
                    {/* Recipe image */}
                    {recipe.imageUrl && (
                        <img
                            src={recipe.imageUrl}
                            alt={recipe.title}
                            className="w-full rounded-xl mb-4 border"
                        />
                    )}

                    {/* Servings */}
                    <div
                        className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 highlight-container-bg mb-4">
                        <p>
                            Für {recipeWorkingCopy.servings.amount} {recipeWorkingCopy.servings.unit}
                        </p>

                        <NumberStepControl
                            value={recipeWorkingCopy.servings.amount}
                            onChange={recalculateIngredients}
                            min={1}
                            className="justify-end sm:justify-center"
                        />
                    </div>

                    {/* Ingredients */}
                    <h2>Zutaten</h2>
                    <ul>
                        {recipeWorkingCopy.ingredientGroupList.map((group, i) => (
                            <div key={i}>
                                {/* the title is optional, only print if present */}
                                {group.title && group.title.trim() !== "" && (
                                    <h3 className="highlight-container-bg mb-2">{group.title}</h3>
                                )}
                                <ul>
                                    {group.ingredientList.map((ing, j) => (
                                        <li key={j} className="border-b border-gray-300 last:border-b-0 p-2">
                                            {ing.amount ?? ""} {ing.unit ?? ""} {ing.name}
                                        </li>
                                    ))}
                                </ul>
                            </div>
                        ))}
                    </ul>

                    {/* Instructions */}
                    <h2>Zubereitung</h2>
                    <ol className="space-y-4">
                        {recipe.instructionStepList.map((step, j) => (
                            <NumberedListItem key={j} index={j} text={step.text}/>
                        ))}
                    </ol>

                    {/* Action buttons */}
                    <div className="button-group">
                        <ButtonLink
                            to={recipe.id !== undefined ? getRecipeEditUrl(recipe.id) : getRecipeListUrl()} // @todo show error instead
                            buttonType={ButtonType.PrimaryButton}
                            text="Bearbeiten"
                        />
                        <ButtonLink
                            to={getRecipeListUrl()}
                            text="Zurueck"
                        />
                    </div>
                </div>
            </div>
        </div>
    )
}
