"""Canonical composition authority and legacy recipe compatibility.

``VerticalRecipe`` remains readable while the catalog is being migrated, but it
is adapted into the canonical ``CompositionRecipe`` shape before planning.  No
planner should need to understand both recipe vocabularies.
"""

from __future__ import annotations

from src.domain.composition_recipes.schemas import CompositionRecipe
from src.domain.starter_library.archetypes import starter_id_for_recipe

if False:  # pragma: no cover - type-checking-only import avoids app_blocks cycle
    from src.domain.app_blocks.vertical_recipes import VerticalRecipe


def composition_recipe_from_vertical(recipe: "VerticalRecipe") -> CompositionRecipe:
    """Convert legacy Fast Lane metadata without changing its persisted ID."""

    return CompositionRecipe(
        slug=recipe.id,
        name=recipe.name,
        description=f"Compatibility import of legacy VerticalRecipe {recipe.id}.",
        project_types=[recipe.archetype],
        starter_id=starter_id_for_recipe(recipe.id) or recipe.archetype,
        required_app_blocks=recipe.required_app_blocks,
        presentation={
            "expected_surfaces": list(recipe.presentation.surfaces)
            if recipe.presentation is not None and hasattr(recipe.presentation, "surfaces")
            else [],
        },
        version=1,
        is_active=True,
    )


def canonical_recipe(
    *,
    composition_recipe: CompositionRecipe | None = None,
    legacy_recipe: "VerticalRecipe | None" = None,
) -> CompositionRecipe | None:
    """Return one semantic recipe; canonical data always wins."""

    if composition_recipe is not None:
        return composition_recipe
    return composition_recipe_from_vertical(legacy_recipe) if legacy_recipe else None
