from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from app.core.deps import get_current_user, require_role from app.db.database import get_db from app.db.models import User from app.schemas.class_ import ClassCreate, ClassUpdate, ClassOut from app.schemas.user import UserListItem from app.schemas.common import PageResponse from app.services.class_service import ( create_class, update_class, delete_class, get_class_by_id, list_classes, get_member_count, get_class_members, ) router = APIRouter(prefix="/api/classes", tags=["classes"]) @router.get("/", response_model=PageResponse[ClassOut]) async def get_classes( page: int = 1, page_size: int = 50, db: AsyncSession = Depends(get_db), ): classes, total = await list_classes(db, page, page_size) total_pages = (total + page_size - 1) // page_size result = [] for c in classes: count = await get_member_count(db, c.id) out = ClassOut.model_validate(c) out.member_count = count result.append(out) return PageResponse( items=result, total=total, page=page, page_size=page_size, total_pages=total_pages ) @router.post("/", response_model=ClassOut) async def create_new_class( data: ClassCreate, admin: User = Depends(require_role("super_admin")), db: AsyncSession = Depends(get_db), ): class_ = await create_class(db, data) out = ClassOut.model_validate(class_) out.member_count = 0 return out @router.put("/{class_id}", response_model=ClassOut) async def update_existing_class( class_id: int, data: ClassUpdate, admin: User = Depends(require_role("super_admin")), db: AsyncSession = Depends(get_db), ): class_ = await get_class_by_id(db, class_id) if class_ is None: raise HTTPException(status_code=404, detail="Class not found") updated = await update_class(db, class_, data) out = ClassOut.model_validate(updated) out.member_count = await get_member_count(db, class_id) return out @router.delete("/{class_id}") async def delete_existing_class( class_id: int, admin: User = Depends(require_role("super_admin")), db: AsyncSession = Depends(get_db), ): class_ = await get_class_by_id(db, class_id) if class_ is None: raise HTTPException(status_code=404, detail="Class not found") await delete_class(db, class_) return {"message": "Class deleted"} @router.get("/{class_id}/members", response_model=PageResponse[UserListItem]) async def get_members( class_id: int, status: str | None = None, page: int = 1, page_size: int = 50, admin: User = Depends(require_role("super_admin", "class_admin")), db: AsyncSession = Depends(get_db), ): if admin.role == "class_admin" and admin.class_id != class_id: raise HTTPException(status_code=403, detail="Access denied for this class") members, total = await get_class_members(db, class_id, status, page, page_size) total_pages = (total + page_size - 1) // page_size return PageResponse( items=[UserListItem.model_validate(m) for m in members], total=total, page=page, page_size=page_size, total_pages=total_pages, ) @router.get("/{class_id}/pending", response_model=PageResponse[UserListItem]) async def get_pending_members( class_id: int, page: int = 1, page_size: int = 50, admin: User = Depends(require_role("super_admin", "class_admin")), db: AsyncSession = Depends(get_db), ): if admin.role == "class_admin" and admin.class_id != class_id: raise HTTPException(status_code=403, detail="Access denied for this class") members, total = await get_class_members(db, class_id, status="pending", page=page, page_size=page_size) total_pages = (total + page_size - 1) // page_size return PageResponse( items=[UserListItem.model_validate(m) for m in members], total=total, page=page, page_size=page_size, total_pages=total_pages, )