from fastapi import APIRouter, Depends, HTTPException, Query, status from sqlalchemy.orm import Session from datetime import datetime, timedelta from typing import List from database import get_db from models import Ingredient from schemas import IngredientCreate, IngredientRead, IngredientUpdate router = APIRouter(prefix="/api/pantry", tags=["pantry"]) @router.get("", response_model=List[IngredientRead]) def list_ingredients( expiring_soon: bool = Query(False), db: Session = Depends(get_db) ): """List all ingredients. Optional query param ?expiring_soon=true filters to ingredients with expiry_date within 7 days from today.""" query = db.query(Ingredient) if expiring_soon: today = datetime.utcnow().date() seven_days_later = today + timedelta(days=7) query = query.filter( (Ingredient.expiry_date >= today) & (Ingredient.expiry_date <= seven_days_later) ) return query.all() @router.get("/expiring", response_model=List[IngredientRead]) def list_expiring_ingredients(db: Session = Depends(get_db)): """Ingredients expiring within 7 days.""" today = datetime.utcnow().date() seven_days_later = today + timedelta(days=7) return db.query(Ingredient).filter( (Ingredient.expiry_date >= today) & (Ingredient.expiry_date <= seven_days_later) ).all() @router.post("", response_model=IngredientRead, status_code=status.HTTP_201_CREATED) def create_ingredient(ingredient: IngredientCreate, db: Session = Depends(get_db)): """Create a new ingredient.""" db_ingredient = Ingredient(**ingredient.model_dump()) db.add(db_ingredient) db.commit() db.refresh(db_ingredient) return db_ingredient @router.put("/{id}", response_model=IngredientRead) def update_ingredient(id: int, ingredient: IngredientUpdate, db: Session = Depends(get_db)): """Update ingredient fields (partial update).""" db_ingredient = db.query(Ingredient).filter(Ingredient.id == id).first() if not db_ingredient: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Ingredient not found") update_data = ingredient.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(db_ingredient, field, value) db_ingredient.updated_at = datetime.utcnow() db.commit() db.refresh(db_ingredient) return db_ingredient @router.delete("/{id}", status_code=status.HTTP_204_NO_CONTENT) def delete_ingredient(id: int, db: Session = Depends(get_db)): """Delete an ingredient.""" db_ingredient = db.query(Ingredient).filter(Ingredient.id == id).first() if not db_ingredient: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Ingredient not found") db.delete(db_ingredient) db.commit() @router.post("/bulk", response_model=List[IngredientRead]) def bulk_upsert_ingredients(ingredients: List[IngredientCreate], db: Session = Depends(get_db)): """Upsert list of ingredients. If an ingredient with same name exists, add the quantity (accumulate). If not, create new.""" result = [] for ingredient_data in ingredients: existing = db.query(Ingredient).filter(Ingredient.name == ingredient_data.name).first() if existing: existing.quantity += ingredient_data.quantity existing.updated_at = datetime.utcnow() db.commit() db.refresh(existing) result.append(existing) else: new_ingredient = Ingredient(**ingredient_data.model_dump()) db.add(new_ingredient) db.commit() db.refresh(new_ingredient) result.append(new_ingredient) return result