"""Tests for Build Your Own recipe assembly schemas."""
from app.models.schemas.recipe import (
    AssemblyRoleOut,
    AssemblyTemplateOut,
    BuildRequest,
    RoleCandidateItem,
    RoleCandidatesResponse,
)


def test_assembly_role_out_schema():
    """Test AssemblyRoleOut schema creation and field access."""
    role = AssemblyRoleOut(
        display="protein",
        required=True,
        keywords=["chicken"],
        hint="Main ingredient"
    )
    assert role.display == "protein"
    assert role.required is True
    assert role.keywords == ["chicken"]
    assert role.hint == "Main ingredient"


def test_assembly_template_out_schema():
    """Test AssemblyTemplateOut schema with nested roles."""
    tmpl = AssemblyTemplateOut(
        id="burrito_taco",
        title="Burrito / Taco",
        icon="🌯",
        descriptor="Protein, veg, and sauce in a tortilla or over rice",
        role_sequence=[
            AssemblyRoleOut(
                display="base",
                required=True,
                keywords=["tortilla"],
                hint="The wrap"
            ),
        ],
    )
    assert tmpl.id == "burrito_taco"
    assert tmpl.title == "Burrito / Taco"
    assert tmpl.icon == "🌯"
    assert len(tmpl.role_sequence) == 1
    assert tmpl.role_sequence[0].display == "base"


def test_role_candidate_item_schema():
    """Test RoleCandidateItem schema with tags."""
    item = RoleCandidateItem(
        name="bell pepper",
        in_pantry=True,
        tags=["sweet", "vegetable"]
    )
    assert item.name == "bell pepper"
    assert item.in_pantry is True
    assert "sweet" in item.tags


def test_role_candidates_response_schema():
    """Test RoleCandidatesResponse with compatible and other candidates."""
    resp = RoleCandidatesResponse(
        compatible=[
            RoleCandidateItem(name="bell pepper", in_pantry=True, tags=["sweet"])
        ],
        other=[
            RoleCandidateItem(
                name="corn",
                in_pantry=False,
                tags=["sweet", "starchy"]
            )
        ],
        available_tags=["sweet", "starchy"],
    )
    assert len(resp.compatible) == 1
    assert resp.compatible[0].name == "bell pepper"
    assert len(resp.other) == 1
    assert "sweet" in resp.available_tags
    assert "starchy" in resp.available_tags


def test_build_request_schema():
    """Test BuildRequest schema with template and role overrides."""
    req = BuildRequest(
        template_id="burrito_taco",
        role_overrides={"protein": "chicken", "sauce": "verde"}
    )
    assert req.template_id == "burrito_taco"
    assert req.role_overrides["protein"] == "chicken"
    assert req.role_overrides["sauce"] == "verde"


def test_role_candidates_response_defaults():
    """Test RoleCandidatesResponse with default factory fields."""
    resp = RoleCandidatesResponse()
    assert resp.compatible == []
    assert resp.other == []
    assert resp.available_tags == []


def test_build_request_defaults():
    """Test BuildRequest with default role_overrides."""
    req = BuildRequest(template_id="test_template")
    assert req.template_id == "test_template"
    assert req.role_overrides == {}


def test_get_templates_for_api_returns_13():
    from app.services.recipe.assembly_recipes import get_templates_for_api
    templates = get_templates_for_api()
    assert len(templates) == 13


def test_get_templates_for_api_shape():
    from app.services.recipe.assembly_recipes import get_templates_for_api
    templates = get_templates_for_api()
    t = next(t for t in templates if t["id"] == "burrito_taco")
    assert t["title"] == "Burrito / Taco"
    assert t["icon"] == "🌯"
    assert isinstance(t["role_sequence"], list)
    assert len(t["role_sequence"]) >= 1
    role = t["role_sequence"][0]
    assert "display" in role
    assert "required" in role
    assert "keywords" in role
    assert "hint" in role


def test_get_templates_for_api_all_have_slugs():
    from app.services.recipe.assembly_recipes import get_templates_for_api
    templates = get_templates_for_api()
    slugs = {t["id"] for t in templates}
    assert len(slugs) == 13
    assert all(isinstance(s, str) and len(s) > 3 for s in slugs)


def test_get_role_candidates_splits_compatible_other():
    from app.services.recipe.assembly_recipes import get_role_candidates
    profile_index = {
        "rice": ["Starch", "Structure"],
        "chicken": ["Protein"],
        "broccoli": ["Vegetable"],
    }
    result = get_role_candidates(
        template_slug="stir_fry",
        role_display="protein",
        pantry_set={"rice", "chicken", "broccoli"},
        prior_picks=["rice"],
        profile_index=profile_index,
    )
    assert isinstance(result["compatible"], list)
    assert isinstance(result["other"], list)
    assert isinstance(result["available_tags"], list)
    all_names = [c["name"] for c in result["compatible"] + result["other"]]
    assert "chicken" in all_names


def test_get_role_candidates_available_tags():
    from app.services.recipe.assembly_recipes import get_role_candidates
    profile_index = {
        "chicken": ["Protein", "Umami"],
        "tofu": ["Protein"],
    }
    result = get_role_candidates(
        template_slug="stir_fry",
        role_display="protein",
        pantry_set={"chicken", "tofu"},
        prior_picks=[],
        profile_index=profile_index,
    )
    assert "Protein" in result["available_tags"]


def test_get_role_candidates_unknown_template_returns_empty():
    from app.services.recipe.assembly_recipes import get_role_candidates
    result = get_role_candidates(
        template_slug="nonexistent_template",
        role_display="protein",
        pantry_set={"chicken"},
        prior_picks=[],
        profile_index={},
    )
    assert result == {"compatible": [], "other": [], "available_tags": []}


def test_build_from_selection_returns_recipe():
    from app.services.recipe.assembly_recipes import build_from_selection
    result = build_from_selection(
        template_slug="burrito_taco",
        role_overrides={"tortilla or wrap": "flour tortilla", "protein": "chicken"},
        pantry_set={"flour tortilla", "chicken", "salsa"},
    )
    assert result is not None
    assert len(result.directions) > 0
    assert result.id == -1


def test_build_from_selection_missing_required_role_returns_none():
    from app.services.recipe.assembly_recipes import build_from_selection
    result = build_from_selection(
        template_slug="burrito_taco",
        role_overrides={"protein": "chicken"},
        pantry_set={"chicken"},
    )
    assert result is None


def test_build_from_selection_unknown_template_returns_none():
    from app.services.recipe.assembly_recipes import build_from_selection
    result = build_from_selection(
        template_slug="does_not_exist",
        role_overrides={},
        pantry_set={"chicken"},
    )
    assert result is None
