from fastapi import APIRouter, Depends, HTTPException, status, Query from ..utils.response_helpers import success_response from sqlalchemy.orm import Session from typing import Optional from ..config.database import get_db from ..config.logging_config import get_logger from ..middleware.auth import get_current_user, authorize_roles from ..models.user import User from ..models.review import Review, ReviewStatus from ..models.room import Room from ..schemas.review import CreateReviewRequest logger = get_logger(__name__) router = APIRouter(prefix='/reviews', tags=['reviews']) @router.get('/room/{room_id}') async def get_room_reviews( room_id: int, page: int = Query(1, ge=1), limit: int = Query(10, ge=1, le=100), db: Session = Depends(get_db) ): try: query = db.query(Review).filter(Review.room_id == room_id, Review.status == ReviewStatus.approved) total = query.count() offset = (page - 1) * limit reviews = query.order_by(Review.created_at.desc()).offset(offset).limit(limit).all() result = [] for review in reviews: review_dict = {'id': review.id, 'user_id': review.user_id, 'room_id': review.room_id, 'rating': review.rating, 'comment': review.comment, 'status': review.status.value if isinstance(review.status, ReviewStatus) else review.status, 'created_at': review.created_at.isoformat() if review.created_at else None} if review.user: review_dict['user'] = {'id': review.user.id, 'full_name': review.user.full_name, 'email': review.user.email} result.append(review_dict) return { 'status': 'success', 'data': { 'reviews': result, 'pagination': { 'total': total, 'page': page, 'limit': limit, 'totalPages': (total + limit - 1) // limit } } } except Exception as e: db.rollback() logger.error(f'Error fetching room reviews: {str(e)}', exc_info=True) raise HTTPException(status_code=500, detail=str(e)) @router.get('/', dependencies=[Depends(authorize_roles('admin'))]) async def get_all_reviews(status_filter: Optional[str]=Query(None, alias='status'), page: int=Query(1, ge=1), limit: int=Query(10, ge=1, le=100), current_user: User=Depends(authorize_roles('admin')), db: Session=Depends(get_db)): try: query = db.query(Review) if status_filter: try: query = query.filter(Review.status == ReviewStatus(status_filter)) except ValueError: pass total = query.count() offset = (page - 1) * limit reviews = query.order_by(Review.created_at.desc()).offset(offset).limit(limit).all() result = [] for review in reviews: review_dict = {'id': review.id, 'user_id': review.user_id, 'room_id': review.room_id, 'rating': review.rating, 'comment': review.comment, 'status': review.status.value if isinstance(review.status, ReviewStatus) else review.status, 'created_at': review.created_at.isoformat() if review.created_at else None} if review.user: review_dict['user'] = {'id': review.user.id, 'full_name': review.user.full_name, 'email': review.user.email, 'phone': review.user.phone} if review.room: review_dict['room'] = {'id': review.room.id, 'room_number': review.room.room_number} result.append(review_dict) return {'status': 'success', 'data': {'reviews': result, 'pagination': {'total': total, 'page': page, 'limit': limit, 'totalPages': (total + limit - 1) // limit}}} except Exception as e: db.rollback() logger.error(f'Error fetching all reviews: {str(e)}', exc_info=True) raise HTTPException(status_code=500, detail=str(e)) @router.post('/') async def create_review(review_data: CreateReviewRequest, current_user: User=Depends(get_current_user), db: Session=Depends(get_db)): try: room_id = review_data.room_id rating = review_data.rating comment = review_data.comment 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(Review).filter(Review.user_id == current_user.id, Review.room_id == room_id).first() if existing: raise HTTPException(status_code=400, detail='You have already reviewed this room') review = Review(user_id=current_user.id, room_id=room_id, rating=rating, comment=comment, status=ReviewStatus.pending) db.add(review) db.commit() db.refresh(review) return {'status': 'success', 'message': 'Review submitted successfully and is pending approval', 'data': {'review': review}} except HTTPException: raise except Exception as e: db.rollback() logger.error(f'Error creating review: {str(e)}', exc_info=True) raise HTTPException(status_code=500, detail=str(e)) @router.put('/{id}/approve', dependencies=[Depends(authorize_roles('admin'))]) async def approve_review(id: int, current_user: User=Depends(authorize_roles('admin')), db: Session=Depends(get_db)): try: review = db.query(Review).filter(Review.id == id).first() if not review: raise HTTPException(status_code=404, detail='Review not found') review.status = ReviewStatus.approved db.commit() db.refresh(review) return {'status': 'success', 'message': 'Review approved successfully', 'data': {'review': review}} except HTTPException: raise except Exception as e: db.rollback() logger.error(f'Error approving review: {str(e)}', exc_info=True) raise HTTPException(status_code=500, detail=str(e)) @router.put('/{id}/reject', dependencies=[Depends(authorize_roles('admin'))]) async def reject_review(id: int, current_user: User=Depends(authorize_roles('admin')), db: Session=Depends(get_db)): try: review = db.query(Review).filter(Review.id == id).first() if not review: raise HTTPException(status_code=404, detail='Review not found') review.status = ReviewStatus.rejected db.commit() db.refresh(review) return {'status': 'success', 'message': 'Review rejected successfully', 'data': {'review': review}} except HTTPException: raise except Exception as e: db.rollback() logger.error(f'Error rejecting review: {str(e)}', exc_info=True) raise HTTPException(status_code=500, detail=str(e)) @router.delete('/{id}', dependencies=[Depends(authorize_roles('admin'))]) async def delete_review(id: int, current_user: User=Depends(authorize_roles('admin')), db: Session=Depends(get_db)): try: review = db.query(Review).filter(Review.id == id).first() if not review: raise HTTPException(status_code=404, detail='Review not found') db.delete(review) db.commit() return {'status': 'success', 'message': 'Review deleted successfully'} except HTTPException: raise except Exception as e: db.rollback() logger.error(f'Error deleting review: {str(e)}', exc_info=True) raise HTTPException(status_code=500, detail=str(e))