from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from typing import List from datetime import datetime from ...core.database import get_db from ...models.models import Event, EventRSVP, User, EventStatus from ...schemas import ( EventCreate, EventUpdate, EventResponse, EventRSVPResponse, EventRSVPUpdate, MessageResponse ) from ...api.dependencies import get_current_active_user, get_admin_user router = APIRouter() @router.get("/", response_model=List[EventResponse]) async def get_events( current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Get all events (admin) or published events (members)""" if current_user.role in ['admin', 'super_admin']: events = db.query(Event).order_by(Event.event_date).all() else: events = db.query(Event).filter( Event.status == EventStatus.PUBLISHED ).order_by(Event.event_date).all() return events @router.get("/upcoming", response_model=List[EventResponse]) async def get_upcoming_events( current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Get upcoming events""" now = datetime.now() events = db.query(Event).filter( Event.event_date >= now.date(), Event.status == EventStatus.PUBLISHED ).order_by(Event.event_date).all() return events @router.post("/", response_model=EventResponse, status_code=status.HTTP_201_CREATED) async def create_event( event_data: EventCreate, current_user: User = Depends(get_admin_user), db: Session = Depends(get_db) ): """Create a new event (admin only)""" # Validate event date is in the future if event_data.event_date < datetime.now(): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Event date must be in the future" ) event = Event( title=event_data.title, description=event_data.description, event_date=event_data.event_date, event_time=event_data.event_time, location=event_data.location, max_attendees=event_data.max_attendees, status=EventStatus.DRAFT, created_by=current_user.id ) db.add(event) db.commit() db.refresh(event) return event @router.put("/{event_id}", response_model=EventResponse) async def update_event( event_id: int, event_data: EventUpdate, current_user: User = Depends(get_admin_user), db: Session = Depends(get_db) ): """Update an event (admin only)""" event = db.query(Event).filter(Event.id == event_id).first() if not event: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Event not found" ) # Update fields for field, value in event_data.dict(exclude_unset=True).items(): setattr(event, field, value) event.updated_at = datetime.now() db.commit() db.refresh(event) return event @router.delete("/{event_id}", response_model=MessageResponse) async def delete_event( event_id: int, current_user: User = Depends(get_admin_user), db: Session = Depends(get_db) ): """Delete an event (admin only)""" event = db.query(Event).filter(Event.id == event_id).first() if not event: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Event not found" ) db.delete(event) db.commit() return {"message": "Event deleted successfully"} @router.get("/{event_id}/rsvps", response_model=List[EventRSVPResponse]) async def get_event_rsvps( event_id: int, current_user: User = Depends(get_admin_user), db: Session = Depends(get_db) ): """Get RSVPs for an event (admin only)""" event = db.query(Event).filter(Event.id == event_id).first() if not event: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Event not found" ) rsvps = db.query(EventRSVP).filter(EventRSVP.event_id == event_id).all() return rsvps @router.post("/{event_id}/rsvp", response_model=EventRSVPResponse) async def create_or_update_rsvp( event_id: int, rsvp_data: EventRSVPUpdate, current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Create or update RSVP for an event""" event = db.query(Event).filter(Event.id == event_id).first() if not event: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Event not found" ) if event.status != EventStatus.PUBLISHED: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Event is not available for RSVP" ) # Check if RSVP already exists existing_rsvp = db.query(EventRSVP).filter( EventRSVP.event_id == event_id, EventRSVP.user_id == current_user.id ).first() if existing_rsvp: # Update existing RSVP existing_rsvp.status = rsvp_data.status if rsvp_data.notes is not None: existing_rsvp.notes = rsvp_data.notes existing_rsvp.updated_at = datetime.now() db.commit() db.refresh(existing_rsvp) return existing_rsvp else: # Check attendee limit if event.max_attendees: current_rsvp_count = db.query(EventRSVP).filter( EventRSVP.event_id == event_id, EventRSVP.status == 'attending' ).count() if current_rsvp_count >= event.max_attendees: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Event is at maximum capacity" ) # Create new RSVP rsvp = EventRSVP( event_id=event_id, user_id=current_user.id, status=rsvp_data.status, notes=rsvp_data.notes ) db.add(rsvp) db.commit() db.refresh(rsvp) return rsvp @router.get("/my-rsvps", response_model=List[EventRSVPResponse]) async def get_my_rsvps( current_user: User = Depends(get_current_active_user), db: Session = Depends(get_db) ): """Get current user's RSVPs""" rsvps = db.query(EventRSVP).filter(EventRSVP.user_id == current_user.id).all() return rsvps