from datetime import date
from decimal import Decimal
from uuid import UUID, uuid4

import pytest

pytestmark = pytest.mark.requires_postgres


def test_generate_meal_plan_against_seeded_data():
    """Smoke test: with the seeded 30 recipes and a seeded grocery scrape,
    generate produces a MealPlan with up to 3 items.
    """
    from datetime import datetime, timezone

    from app.database import SessionLocal
    from app.models import (
        FamilyProfile,
        GroceryItem,
        Ingredient,
        IngredientGroceryMatch,
        IngredientMatchSource,
        MealPlan,
        MealPlanItem,
    )
    from app.services.matcher import run_match_job
    from app.services.planner.generate import generate_meal_plan

    setup = SessionLocal()
    try:
        family = FamilyProfile(
            id=uuid4(),
            name="Generate Smoke Family",
            household_size=4,
            adult_count=2,
            child_count=2,
            calorie_target=500,
        )
        setup.add(family)
        setup.commit()
        family_id = family.id

        # Seed at least one grocery_item per ingredient that the recipes use
        # so cost matching can find prices. Pick a handful to keep runtime low.
        for ing in setup.query(Ingredient).limit(20).all():
            setup.add(
                GroceryItem(
                    id=uuid4(),
                    name=ing.name,
                    source="lucky_california",
                    external_id=f"ext-test-{ing.id}",
                    current_price=Decimal("3.99"),
                    regular_price=Decimal("4.99"),
                    is_on_sale=True,
                    scraped_at=datetime.now(timezone.utc),
                )
            )
        setup.commit()
    finally:
        setup.close()

    work = SessionLocal()
    try:
        run_match_job(work)
        result = generate_meal_plan(work, family_id=family_id, week_start_date=date(2026, 5, 11))
        assert result.meal_plan_id is not None
        assert 1 <= len(result.selected) <= 3  # at least 1, at most 3
        plan = work.query(MealPlan).filter(MealPlan.id == result.meal_plan_id).first()
        assert plan is not None
        items = work.query(MealPlanItem).filter(MealPlanItem.meal_plan_id == plan.id).all()
        assert len(items) == len(result.selected)
    finally:
        cleanup = SessionLocal()
        try:
            cleanup.query(MealPlanItem).filter(
                MealPlanItem.meal_plan_id.in_(
                    [r[0] for r in cleanup.query(MealPlan.id).filter(MealPlan.family_profile_id == family_id).all()]
                )
            ).delete(synchronize_session=False)
            cleanup.query(MealPlan).filter(MealPlan.family_profile_id == family_id).delete(synchronize_session=False)
            cleanup.query(FamilyProfile).filter(FamilyProfile.id == family_id).delete(synchronize_session=False)
            cleanup.query(GroceryItem).filter(GroceryItem.external_id.like("ext-test-%")).delete(synchronize_session=False)
            cleanup.query(IngredientGroceryMatch).filter(
                IngredientGroceryMatch.source == IngredientMatchSource.AUTO
            ).delete(synchronize_session=False)
            cleanup.commit()
        finally:
            cleanup.close()
        work.close()
