from fastapi import APIRouter, Depends, HTTPException, status, Query from sqlalchemy.orm import Session from typing import Optional from ..config.database import get_db 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 router = APIRouter(prefix="/reviews", tags=["reviews"]) @router.get("/room/{room_id}") async def get_room_reviews(room_id: int, db: Session = Depends(get_db)): """Get reviews for a room""" try: reviews = db.query(Review).filter( Review.room_id == room_id, Review.status == ReviewStatus.approved ).order_by(Review.created_at.desc()).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} } except Exception as e: 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) ): """Get all reviews (Admin only)""" 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: raise HTTPException(status_code=500, detail=str(e)) @router.post("/") async def create_review( review_data: dict, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """Create new review""" try: room_id = review_data.get("room_id") rating = review_data.get("rating") comment = review_data.get("comment") # Check if room exists room = db.query(Room).filter(Room.id == room_id).first() if not room: raise HTTPException(status_code=404, detail="Room not found") # Check if user already reviewed this room 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" ) # Create review 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() 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) ): """Approve review (Admin only)""" 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() 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) ): """Reject review (Admin only)""" 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() 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) ): """Delete review (Admin only)""" 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() raise HTTPException(status_code=500, detail=str(e))