from typing import List, Optional from fastapi import HTTPException, status, Depends from sqlalchemy.ext.asyncio import AsyncSession from app.models.menu import MenuItem, Category from ..db.crud import ( get_menu_items, get_menu_item_by_id, create_menu_item_db, update_menu_item_db, delete_menu_item_db, get_categories_db ) from ..db.database import get_db class MenuService: def __init__(self, db: AsyncSession = Depends(get_db)): self.db = db async def get_menu_items(self) -> List[MenuItem]: """Get all menu items.""" try: menu_items = await get_menu_items(self.db) if not menu_items: return [] return menu_items except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to fetch menu items: {str(e)}" ) async def create_menu_item(self, item: MenuItem) -> MenuItem: """Create a new menu item.""" await self.validate_menu_item(item) try: return await create_menu_item_db(self.db, item) except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to create menu item: {str(e)}" ) async def update_menu_item(self, item_id: int, item: MenuItem) -> Optional[MenuItem]: """Update an existing menu item.""" await self.validate_menu_item(item) existing_item = await get_menu_item_by_id(self.db, item_id) if not existing_item: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Menu item not found" ) try: updated_item = await update_menu_item_db(self.db, item_id, item) return updated_item except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to update menu item: {str(e)}" ) async def delete_menu_item(self, item_id: int) -> bool: """Delete a menu item.""" existing_item = await get_menu_item_by_id(self.db, item_id) if not existing_item: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Menu item not found" ) try: success = await delete_menu_item_db(self.db, item_id) return success except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to delete menu item: {str(e)}" ) async def get_categories(self) -> List[Category]: """Get all menu categories. Returns: List[Category]: List of all available categories Raises: HTTPException: If there's a database error """ try: categories = await get_categories_db(self.db) if not categories: return [] return categories except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to fetch categories: {str(e)}" ) async def validate_menu_item(self, item: MenuItem) -> None: """Validate menu item data. Args: item (MenuItem): The menu item to validate Raises: HTTPException: If validation fails """ if not item: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Menu item cannot be null" ) if item.price <= 0: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Price must be greater than zero" ) if not item.name.strip(): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Item name cannot be empty" ) if not item.category_id: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Category ID is required" ) if item.description and len(item.description) > 500: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Description is too long (max 500 characters)" )