# app/api/v1/endpoints/costs.py import logging from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.api.dependencies import get_current_user from app.models import User as UserModel # For get_current_user dependency from app.schemas.cost import ListCostSummary from app.crud import cost as crud_cost from app.crud import list as crud_list # For permission checking from app.core.exceptions import ListNotFoundError, ListPermissionError, UserNotFoundError logger = logging.getLogger(__name__) router = APIRouter() @router.get( "/lists/{list_id}/cost-summary", response_model=ListCostSummary, summary="Get Cost Summary for a List", tags=["Costs"], responses={ status.HTTP_403_FORBIDDEN: {"description": "User does not have permission to access this list"}, status.HTTP_404_NOT_FOUND: {"description": "List or associated user not found"} } ) async def get_list_cost_summary( list_id: int, db: AsyncSession = Depends(get_db), current_user: UserModel = Depends(get_current_user), ): """ Retrieves a calculated cost summary for a specific list, detailing total costs, equal shares per user, and individual user balances based on their contributions. The user must have access to the list to view its cost summary. Costs are split among group members if the list belongs to a group, or just for the creator if it's a personal list. All users who added items with prices are included in the calculation. """ logger.info(f"User {current_user.email} requesting cost summary for list {list_id}") # 1. Verify user has access to the target list try: await crud_list.check_list_permission(db=db, list_id=list_id, user_id=current_user.id) except ListPermissionError as e: logger.warning(f"Permission denied for user {current_user.email} on list {list_id}: {str(e)}") raise # Re-raise the original exception to be handled by FastAPI except ListNotFoundError as e: logger.warning(f"List {list_id} not found when checking permissions for cost summary: {str(e)}") raise # Re-raise # 2. Calculate the cost summary try: cost_summary = await crud_cost.calculate_list_cost_summary(db=db, list_id=list_id) logger.info(f"Successfully generated cost summary for list {list_id} for user {current_user.email}") return cost_summary except ListNotFoundError as e: logger.warning(f"List {list_id} not found during cost summary calculation: {str(e)}") # This might be redundant if check_list_permission already confirmed list existence, # but calculate_list_cost_summary also fetches the list. raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e)) except UserNotFoundError as e: logger.error(f"User not found during cost summary calculation for list {list_id}: {str(e)}") # This indicates a data integrity issue (e.g., list creator or item adder missing) raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e)) except Exception as e: logger.error(f"Unexpected error generating cost summary for list {list_id} for user {current_user.email}: {str(e)}", exc_info=True) raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="An unexpected error occurred while generating the cost summary.")