from uuid import UUID from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from app.auth.dependencies import get_current_user, require_roles from app.models import Group from app.models.auth import CognitoUser from app.models.schemas import ( GroupBulkSort, GroupCreate, GroupResponse, GroupSortUpdate, GroupUpdate, ) from app.utils.database import get_db router = APIRouter(prefix="/groups", tags=["groups"]) @router.post("/", response_model=GroupResponse, status_code=status.HTTP_201_CREATED) @require_roles("admin") def create_group( group: GroupCreate, db: Session = Depends(get_db), user: CognitoUser = Depends(get_current_user), ): """Create a new channel group""" # Check for duplicate group name existing_group = db.query(Group).filter(Group.name == group.name).first() if existing_group: raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail="Group with this name already exists", ) db_group = Group(**group.model_dump()) db.add(db_group) db.commit() db.refresh(db_group) return db_group @router.get("/{group_id}", response_model=GroupResponse) def get_group(group_id: UUID, db: Session = Depends(get_db)): """Get a group by id""" group = db.query(Group).filter(Group.id == group_id).first() if not group: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Group not found" ) return group @router.put("/{group_id}", response_model=GroupResponse) @require_roles("admin") def update_group( group_id: UUID, group: GroupUpdate, db: Session = Depends(get_db), user: CognitoUser = Depends(get_current_user), ): """Update a group's name or sort order""" db_group = db.query(Group).filter(Group.id == group_id).first() if not db_group: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Group not found" ) # Check for duplicate name if name is being updated if group.name is not None and group.name != db_group.name: existing_group = db.query(Group).filter(Group.name == group.name).first() if existing_group: raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail="Group with this name already exists", ) # Update only provided fields update_data = group.model_dump(exclude_unset=True) for key, value in update_data.items(): setattr(db_group, key, value) db.commit() db.refresh(db_group) return db_group @router.delete("/{group_id}", status_code=status.HTTP_204_NO_CONTENT) @require_roles("admin") def delete_group( group_id: UUID, db: Session = Depends(get_db), user: CognitoUser = Depends(get_current_user), ): """Delete a group (only if it has no channels)""" group = db.query(Group).filter(Group.id == group_id).first() if not group: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Group not found" ) # Check if group has any channels if group.channels: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Cannot delete group with existing channels", ) db.delete(group) db.commit() return None @router.get("/", response_model=list[GroupResponse]) def list_groups(db: Session = Depends(get_db)): """List all groups sorted by sort_order""" return db.query(Group).order_by(Group.sort_order).all() @router.put("/{group_id}/sort", response_model=GroupResponse) @require_roles("admin") def update_group_sort_order( group_id: UUID, sort_update: GroupSortUpdate, db: Session = Depends(get_db), user: CognitoUser = Depends(get_current_user), ): """Update a single group's sort order""" db_group = db.query(Group).filter(Group.id == group_id).first() if not db_group: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Group not found" ) db_group.sort_order = sort_update.sort_order db.commit() db.refresh(db_group) return db_group @router.post("/reorder", response_model=list[GroupResponse]) @require_roles("admin") def bulk_update_sort_orders( bulk_sort: GroupBulkSort, db: Session = Depends(get_db), user: CognitoUser = Depends(get_current_user), ): """Bulk update group sort orders""" groups_to_update = [] for group_data in bulk_sort.groups: group_id = group_data["group_id"] sort_order = group_data["sort_order"] group = db.query(Group).filter(Group.id == str(group_id)).first() if not group: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Group with id {group_id} not found", ) group.sort_order = sort_order groups_to_update.append(group) db.commit() # Return all groups in their new order return db.query(Group).order_by(Group.sort_order).all()