from __future__ import annotations from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from app.db.session import get_db from app.core.security import get_current_user, require_roles, UserClaims from app.schemas.pair import PairCreate, PairUpdate, PairRead from app.services.pair_service import PairService router = APIRouter(prefix="/v1/pairs", tags=["pairs"]) @router.post("", response_model=PairRead, status_code=201) def create_pair(payload: PairCreate, db: Session = Depends(get_db), user: UserClaims = Depends(require_roles("ADMIN","MATCHMAKER"))): svc = PairService(db) return svc.create(user_id_a=payload.user_id_a, user_id_b=payload.user_id_b, score=payload.score, notes=payload.notes, created_by=user.sub) @router.get("", response_model=list[PairRead]) def list_pairs(for_user_id: str | None = None, status: str | None = None, offset: int = 0, limit: int = Query(50, le=200), db: Session = Depends(get_db), _: UserClaims = Depends(get_current_user)): return PairService(db).list(for_user_id=for_user_id, status=status, offset=offset, limit=limit) @router.get("/{pair_id}", response_model=PairRead) def get_pair(pair_id: str, db: Session = Depends(get_db), _: UserClaims = Depends(get_current_user)): obj = PairService(db).get(pair_id) if not obj: raise HTTPException(status_code=404, detail="Not found") return obj @router.patch("/{pair_id}", response_model=PairRead) def update_pair(pair_id: str, payload: PairUpdate, db: Session = Depends(get_db), _: UserClaims = Depends(require_roles("ADMIN","MATCHMAKER"))): svc = PairService(db) obj = svc.get(pair_id) if not obj: raise HTTPException(status_code=404, detail="Not found") return svc.update(obj, **payload.model_dump(exclude_none=True)) @router.post("/{pair_id}/accept", response_model=PairRead) def accept(pair_id: str, db: Session = Depends(get_db), user: UserClaims = Depends(get_current_user)): svc = PairService(db) obj = svc.get(pair_id) if not obj: raise HTTPException(status_code=404, detail="Not found") # Validate that current user participates if user.sub not in (str(obj.user_id_a), str(obj.user_id_b)): raise HTTPException(status_code=403, detail="Not allowed") return svc.set_status(obj, "accepted") @router.post("/{pair_id}/reject", response_model=PairRead) def reject(pair_id: str, db: Session = Depends(get_db), user: UserClaims = Depends(get_current_user)): svc = PairService(db) obj = svc.get(pair_id) if not obj: raise HTTPException(status_code=404, detail="Not found") if user.sub not in (str(obj.user_id_a), str(obj.user_id_b)): raise HTTPException(status_code=403, detail="Not allowed") return svc.set_status(obj, "rejected") @router.delete("/{pair_id}", status_code=204) def delete_pair(pair_id: str, db: Session = Depends(get_db), _: UserClaims = Depends(require_roles("ADMIN","MATCHMAKER"))): svc = PairService(db) obj = svc.get(pair_id) if not obj: return svc.delete(obj)