from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from sqlalchemy import func from ...shared.config.database import get_db from ...security.middleware.auth import get_current_user from ...auth.models.user import User from ...auth.models.role import Role from ..models.favorite import Favorite from ...rooms.models.room import Room from ...rooms.models.room_type import RoomType from ..models.review import Review, ReviewStatus router = APIRouter(prefix='/favorites', tags=['favorites']) @router.get('/') async def get_favorites(current_user: User=Depends(get_current_user), db: Session=Depends(get_db)): # PERFORMANCE: Use eager-loaded role relationship if available if hasattr(current_user, 'role') and current_user.role is not None: role_name = current_user.role.name else: # Fallback: query if relationship wasn't loaded role = db.query(Role).filter(Role.id == current_user.role_id).first() role_name = role.name if role else 'customer' if role_name in ['admin', 'staff', 'accountant']: raise HTTPException(status_code=403, detail='Admin, staff, and accountant users cannot have favorites') try: favorites = db.query(Favorite).filter(Favorite.user_id == current_user.id).order_by(Favorite.created_at.desc()).all() result = [] for favorite in favorites: if not favorite.room: continue room = favorite.room review_stats = db.query(func.avg(Review.rating).label('average_rating'), func.count(Review.id).label('total_reviews')).filter(Review.room_id == room.id, Review.status == ReviewStatus.approved).first() room_dict = {'id': room.id, 'room_type_id': room.room_type_id, 'room_number': room.room_number, 'floor': room.floor, 'status': room.status.value if hasattr(room.status, 'value') else room.status, 'price': float(room.price) if room.price else 0.0, 'featured': room.featured, 'description': room.description, 'amenities': room.amenities, 'images': room.images or [], 'average_rating': round(float(review_stats.average_rating or 0), 1) if review_stats and review_stats.average_rating else None, 'total_reviews': review_stats.total_reviews or 0 if review_stats else 0} if room.room_type: room_dict['room_type'] = {'id': room.room_type.id, 'name': room.room_type.name, 'description': room.room_type.description, 'base_price': float(room.room_type.base_price) if room.room_type.base_price else 0.0, 'capacity': room.room_type.capacity, 'amenities': room.room_type.amenities} favorite_dict = {'id': favorite.id, 'user_id': favorite.user_id, 'room_id': favorite.room_id, 'room': room_dict, 'created_at': favorite.created_at.isoformat() if favorite.created_at else None} result.append(favorite_dict) return {'status': 'success', 'data': {'favorites': result, 'total': len(result)}} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @router.post('/{room_id}') async def add_favorite(room_id: int, current_user: User=Depends(get_current_user), db: Session=Depends(get_db)): # PERFORMANCE: Use eager-loaded role relationship if available if hasattr(current_user, 'role') and current_user.role is not None: role_name = current_user.role.name else: # Fallback: query if relationship wasn't loaded role = db.query(Role).filter(Role.id == current_user.role_id).first() role_name = role.name if role else 'customer' if role_name in ['admin', 'staff', 'accountant']: raise HTTPException(status_code=403, detail='Admin, staff, and accountant users cannot add favorites') try: room = db.query(Room).filter(Room.id == room_id).first() if not room: raise HTTPException(status_code=404, detail='Room not found') existing = db.query(Favorite).filter(Favorite.user_id == current_user.id, Favorite.room_id == room_id).first() if existing: raise HTTPException(status_code=400, detail='Room already in favorites list') favorite = Favorite(user_id=current_user.id, room_id=room_id) db.add(favorite) db.commit() db.refresh(favorite) return {'status': 'success', 'message': 'Added to favorites list', 'data': {'favorite': favorite}} except HTTPException: raise except Exception as e: db.rollback() raise HTTPException(status_code=500, detail=str(e)) @router.delete('/{room_id}') async def remove_favorite(room_id: int, current_user: User=Depends(get_current_user), db: Session=Depends(get_db)): # PERFORMANCE: Use eager-loaded role relationship if available if hasattr(current_user, 'role') and current_user.role is not None: role_name = current_user.role.name else: # Fallback: query if relationship wasn't loaded role = db.query(Role).filter(Role.id == current_user.role_id).first() role_name = role.name if role else 'customer' if role_name in ['admin', 'staff', 'accountant']: raise HTTPException(status_code=403, detail='Admin, staff, and accountant users cannot remove favorites') try: favorite = db.query(Favorite).filter(Favorite.user_id == current_user.id, Favorite.room_id == room_id).first() if not favorite: raise HTTPException(status_code=404, detail='Room not found in favorites list') db.delete(favorite) db.commit() return {'status': 'success', 'message': 'Removed from favorites list'} except HTTPException: raise except Exception as e: db.rollback() raise HTTPException(status_code=500, detail=str(e)) @router.get('/check/{room_id}') async def check_favorite(room_id: int, current_user: User=Depends(get_current_user), db: Session=Depends(get_db)): # PERFORMANCE: Use eager-loaded role relationship if available if hasattr(current_user, 'role') and current_user.role is not None: role_name = current_user.role.name else: # Fallback: query if relationship wasn't loaded role = db.query(Role).filter(Role.id == current_user.role_id).first() role_name = role.name if role else 'customer' if role_name in ['admin', 'staff', 'accountant']: return {'status': 'success', 'data': {'isFavorited': False}} try: favorite = db.query(Favorite).filter(Favorite.user_id == current_user.id, Favorite.room_id == room_id).first() return {'status': 'success', 'data': {'isFavorited': favorite is not None}} except Exception as e: raise HTTPException(status_code=500, detail=str(e))