summaryrefslogtreecommitdiff
path: root/routers/menus.py
blob: 49c4654935a13dc81b0d5bd3e40e31e003026d6e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from datetime import datetime, timedelta, date
import json

from database import get_db
from schemas import MenuPlanRead
from models import MenuPlan, Recipe
from services import pantry_service, ai_service
from config import settings

router = APIRouter(prefix="/api/menus", tags=["menus"])


@router.get("/current")
async def get_current_menu(db: Session = Depends(get_db)):
    """Get menu plan for current week."""
    today = datetime.utcnow().date()
    monday = today - timedelta(days=today.weekday())

    menu = db.query(MenuPlan).filter(MenuPlan.week_start == monday).first()
    if not menu:
        raise HTTPException(status_code=404, detail="No menu plan for current week")
    return MenuPlanRead.from_orm(menu)


@router.post("/generate")
async def generate_menu(request: dict = None, db: Session = Depends(get_db)):
    """Generate a weekly menu using AI."""
    # Parse request body
    week_start = None
    if request and isinstance(request, dict):
        week_start = request.get("week_start")

    # Determine week_start date
    if week_start:
        try:
            if isinstance(week_start, str):
                week_start = datetime.fromisoformat(week_start).date()
            else:
                week_start = week_start
        except Exception:
            raise HTTPException(status_code=400, detail="Invalid week_start date")
    else:
        today = datetime.utcnow().date()
        week_start = today - timedelta(days=today.weekday())

    # Build pantry context and generate menu
    try:
        pantry_context = pantry_service.build_pantry_context(db)
        ai_result = await ai_service.generate_weekly_menu(pantry_context)
    except ValueError as e:
        raise HTTPException(status_code=503, detail=str(e))
    except (ConnectionError, Exception) as e:
        raise HTTPException(status_code=503, detail=f"Ollama service error: {str(e)}")

    # Save recipes and build plan dict
    week_plan = ai_result.get("week_plan", {})
    plan_dict = {}

    for day, meals in week_plan.items():
        plan_dict[day] = {}
        for meal_type, meal_data in meals.items():
            if isinstance(meal_data, dict) and "name" in meal_data:
                meal_name = meal_data["name"]

                # Check if recipe exists by name
                existing_recipe = db.query(Recipe).filter(Recipe.name == meal_name).first()
                if existing_recipe:
                    recipe_id = existing_recipe.id
                else:
                    # Create new recipe
                    new_recipe = Recipe(
                        name=meal_name,
                        meal_type=meal_type,
                        ingredients=json.dumps(meal_data.get("ingredients", [])),
                        instructions=meal_data.get("instructions", ""),
                        estimated_time_minutes=meal_data.get("time_minutes", 30),
                        servings=meal_data.get("serves", 2),
                        source="ai",
                    )
                    db.add(new_recipe)
                    db.flush()
                    recipe_id = new_recipe.id

                plan_dict[day][meal_type] = recipe_id

    # Upsert MenuPlan
    existing_plan = db.query(MenuPlan).filter(MenuPlan.week_start == week_start).first()
    if existing_plan:
        existing_plan.plan = json.dumps(plan_dict)
        existing_plan.generated_at = datetime.utcnow()
        existing_plan.model_used = settings.model_name
        menu = existing_plan
    else:
        menu = MenuPlan(
            week_start=week_start,
            plan=json.dumps(plan_dict),
            generated_at=datetime.utcnow(),
            model_used=settings.model_name,
        )
        db.add(menu)

    db.commit()
    db.refresh(menu)

    return {
        "menu_plan": MenuPlanRead.from_orm(menu),
        "week_plan": week_plan,
        "notes": ai_result.get("notes", ""),
    }


@router.get("")
async def list_menus(db: Session = Depends(get_db)):
    """List all menu plans."""
    menus = db.query(MenuPlan).order_by(MenuPlan.week_start.desc()).all()
    return [MenuPlanRead.from_orm(m) for m in menus]


@router.get("/{week_start}")
async def get_menu(week_start: date, db: Session = Depends(get_db)):
    """Get menu plan for a specific week."""
    menu = db.query(MenuPlan).filter(MenuPlan.week_start == week_start).first()
    if not menu:
        raise HTTPException(status_code=404, detail="Menu plan not found")
    return MenuPlanRead.from_orm(menu)


@router.delete("/{id}")
async def delete_menu(id: int, db: Session = Depends(get_db)):
    """Delete a menu plan."""
    menu = db.query(MenuPlan).filter(MenuPlan.id == id).first()
    if not menu:
        raise HTTPException(status_code=404, detail="Menu plan not found")
    db.delete(menu)
    db.commit()
    return {"status": "deleted"}