from typing import Any, Optional from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from app import crud, models, schemas from app.api import deps from app.models.bet import BetStatus router = APIRouter() @router.get("/", response_model=list[schemas.Bet]) def read_bets( db: Session = Depends(deps.get_db), skip: int = 0, limit: int = 100, status: Optional[BetStatus] = None, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Retrieve bets for current user. """ bets = crud.get_user_bets( db, user_id=current_user.id, skip=skip, limit=limit, status=status, ) return bets @router.post("/", response_model=schemas.Bet) def create_bet( *, db: Session = Depends(deps.get_db), bet_in: schemas.BetCreate, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Create a new bet. """ # Check if user has enough balance if current_user.balance < bet_in.amount: raise HTTPException( status_code=400, detail="Insufficient balance for this bet", ) # Check if amount is positive if bet_in.amount <= 0: raise HTTPException( status_code=400, detail="Bet amount must be greater than 0", ) # Check if outcome exists and is active outcome = crud.get_outcome(db, outcome_id=bet_in.outcome_id) if not outcome: raise HTTPException(status_code=404, detail="Outcome not found") if not outcome.is_active: raise HTTPException(status_code=400, detail="This outcome is not available for betting") # Check if market is active if not outcome.market.is_active: raise HTTPException(status_code=400, detail="This market is not available for betting") # Check if event is upcoming or live event = outcome.market.event if event.status not in [models.event.EventStatus.UPCOMING, models.event.EventStatus.LIVE]: raise HTTPException( status_code=400, detail=f"Cannot place bets on events with status {event.status}", ) bet = crud.create_bet(db, bet_in=bet_in, user_id=current_user.id) if not bet: raise HTTPException(status_code=400, detail="Could not create bet") return bet @router.get("/{bet_id}", response_model=schemas.Bet) def read_bet( *, db: Session = Depends(deps.get_db), bet_id: int, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Get specific bet by ID. """ bet = crud.get_bet(db, bet_id=bet_id) if not bet: raise HTTPException(status_code=404, detail="Bet not found") # Only allow user to see their own bets (or admin) if bet.user_id != current_user.id and not current_user.is_admin: raise HTTPException(status_code=403, detail="Not enough permissions") return bet @router.post("/{bet_id}/cancel", response_model=schemas.Bet) def cancel_bet( *, db: Session = Depends(deps.get_db), bet_id: int, current_user: models.User = Depends(deps.get_current_active_user), ) -> Any: """ Cancel a pending bet. """ bet = crud.get_bet(db, bet_id=bet_id) if not bet: raise HTTPException(status_code=404, detail="Bet not found") # Only allow user to cancel their own bets (or admin) if bet.user_id != current_user.id and not current_user.is_admin: raise HTTPException(status_code=403, detail="Not enough permissions") # Only pending bets can be cancelled if bet.status != BetStatus.PENDING: raise HTTPException( status_code=400, detail=f"Cannot cancel a bet with status {bet.status}", ) # Get the outcome and check if event has started outcome = crud.get_outcome(db, outcome_id=bet.outcome_id) event = outcome.market.event # Only allow cancellation if event hasn't started yet if event.status != models.event.EventStatus.UPCOMING: raise HTTPException( status_code=400, detail="Cannot cancel bets on events that have already started", ) bet = crud.update_bet_status(db, bet_id=bet_id, status=BetStatus.CANCELLED) return bet