from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from app.schemas.guests import GuestCreate, GuestUpdate, GuestRead, GuestWithRSVPResponse, map_rsvp_status_to_guest_status from app.crud.guest import guest_crud from typing import List import uuid from app.core.database import get_db from app.models import GuestStatus from app.crud.rsvp import crud_rsvp from app.schemas.rsvp import RSVPSchemaCreate router = APIRouter() @router.post("/", response_model=GuestRead, operation_id="create_guest") def create_guest(guest_in: GuestCreate, db: Session = Depends(get_db)): if guest_in.invitation_code: existing_guest = guest_crud.get_by_invitation_code(db, guest_in.invitation_code) if existing_guest: raise HTTPException( status_code=400, detail="Guest with this invitation code already exists" ) else: guest_in.invitation_code = str(uuid.uuid4())[:8] guest = guest_crud.create(db, obj_in=guest_in) return guest @router.get("/{guest_id}", response_model=GuestRead, operation_id="get_guest") def read_guest(guest_id: uuid.UUID, db: Session = Depends(get_db)): guest = guest_crud.get(db, guest_id) if not guest: raise HTTPException(status_code=404, detail="Guest not found") return guest @router.get("/", response_model=List[GuestRead], operation_id="get_guests") def read_guests(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): guests = guest_crud.get_multi(db, skip=skip, limit=limit) return guests @router.put("/{guest_id}", response_model=GuestRead, operation_id="update_guest") def update_guest(guest_id: uuid.UUID, guest_in: GuestUpdate, db: Session = Depends(get_db)): guest = guest_crud.get(db, guest_id) if not guest: raise HTTPException(status_code=404, detail="Guest not found") guest = guest_crud.update(db, db_obj=guest, obj_in=guest_in) return guest @router.delete("/{guest_id}", response_model=GuestRead, operation_id="delete_guest") def delete_guest(guest_id: uuid.UUID, db: Session = Depends(get_db)): guest = guest_crud.get(db, guest_id) if not guest: raise HTTPException(status_code=404, detail="Guest not found") guest = guest_crud.remove(db, guest_id=str(guest_id)) return guest @router.patch("/{guest_id}/status", response_model=GuestRead, operation_id='set_guest_status') def set_guest_status(guest_id: uuid.UUID, status: GuestStatus, db: Session = Depends(get_db)): guest = guest_crud.update_status(db, guest_id=guest_id, status=status) if not guest: raise HTTPException(status_code=404, detail="Guest not found") return guest @router.post("/{guest_id}/rsvp", response_model=GuestWithRSVPResponse, operation_id='create_guest_rsvp') def process_guest_rsvp( guest_id: uuid.UUID, rsvp_data: RSVPSchemaCreate, db: Session = Depends(get_db) ): # Start a transaction try: # Update or create RSVP existing_rsvp = crud_rsvp.get_rsvp_by_event_and_guest( db, event_id=rsvp_data.event_id, guest_id=guest_id ) if existing_rsvp: rsvp = crud_rsvp.update(db, db_obj=existing_rsvp, obj_in=rsvp_data) else: rsvp_data.guest_id = guest_id # Ensure guest_id matches URL rsvp = crud_rsvp.create(db, obj_in=rsvp_data) # Update guest status to match RSVP guest_status = map_rsvp_status_to_guest_status(rsvp_data.status) additional_guests = max(0, rsvp_data.number_of_guests - 1) guest = guest_crud.update_status(db, guest_id=guest_id, status=guest_status, number_of_guests=additional_guests) # Both operations succeeded, commit the transaction db.commit() # Return combined response return { "guest": guest, "rsvp": rsvp } except Exception as e: db.rollback() raise HTTPException(status_code=500, detail=f"Failed to process RSVP: {str(e)}")