from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from app.core.deps import ensure_class_access, ensure_class_permission, require_role, resolve_class_id_for_user from app.db.database import get_db from app.db.models import User from app.schemas.schedule import ScheduleCreate, ScheduleUpdate, ScheduleOut from app.schemas.common import PageResponse from app.services.schedule_service import ( create_schedule, update_schedule, delete_schedule, get_schedule_by_id, list_schedules, get_upcoming_schedules, ) router = APIRouter(prefix="/api/schedule", tags=["schedule"]) @router.get("/upcoming", response_model=list[ScheduleOut]) async def get_upcoming( limit: int = 10, class_id: int | None = None, user: User = Depends(require_role("super_admin", "teacher", "student")), db: AsyncSession = Depends(get_db), ): effective_class_id = resolve_class_id_for_user(user, class_id) if effective_class_id is None: return [] ensure_class_access(user, effective_class_id) items = await get_upcoming_schedules(db, effective_class_id, limit) return [ScheduleOut.model_validate(i) for i in items] @router.get("/", response_model=PageResponse[ScheduleOut]) async def get_schedules( type: str | None = None, page: int = 1, page_size: int = 50, class_id: int | None = None, user: User = Depends(require_role("super_admin", "teacher", "student")), db: AsyncSession = Depends(get_db), ): effective_class_id = resolve_class_id_for_user(user, class_id) if effective_class_id is None: return PageResponse(items=[], total=0, page=page, page_size=page_size, total_pages=0) ensure_class_access(user, effective_class_id) items, total = await list_schedules(db, effective_class_id, type, page, page_size) total_pages = (total + page_size - 1) // page_size return PageResponse( items=[ScheduleOut.model_validate(i) for i in items], total=total, page=page, page_size=page_size, total_pages=total_pages, ) @router.post("/", response_model=ScheduleOut) async def create_new_schedule( data: ScheduleCreate, class_id: int | None = None, user: User = Depends(require_role("super_admin", "teacher", "student")), db: AsyncSession = Depends(get_db), ): effective_class_id = resolve_class_id_for_user(user, class_id) if effective_class_id is None: raise HTTPException(status_code=400, detail="You are not assigned to a class") ensure_class_permission(user, "schedule_manage", effective_class_id) item = await create_schedule(db, effective_class_id, data) return ScheduleOut.model_validate(item) @router.put("/{schedule_id}", response_model=ScheduleOut) async def update_existing_schedule( schedule_id: int, data: ScheduleUpdate, user: User = Depends(require_role("super_admin", "teacher", "student")), db: AsyncSession = Depends(get_db), ): item = await get_schedule_by_id(db, schedule_id) if item is None: raise HTTPException(status_code=404, detail="Schedule not found") ensure_class_permission(user, "schedule_manage", item.class_id) updated = await update_schedule(db, item, data) return ScheduleOut.model_validate(updated) @router.delete("/{schedule_id}") async def delete_existing_schedule( schedule_id: int, user: User = Depends(require_role("super_admin", "teacher", "student")), db: AsyncSession = Depends(get_db), ): item = await get_schedule_by_id(db, schedule_id) if item is None: raise HTTPException(status_code=404, detail="Schedule not found") ensure_class_permission(user, "schedule_manage", item.class_id) await delete_schedule(db, item) return {"message": "Schedule deleted"}