"""Challenge endpoints for API v1.""" from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from sqlalchemy import func from typing import List, Optional import datetime from backend.models.challenge import Challenge from backend.models.tracking import Tracking from backend.models.user import User from backend import auth from backend.schemas.challenge import ChallengeCreate, ChallengeResponse from backend.schemas.tracking import TrackingCreate, TrackingResponse from backend.database import get_db router = APIRouter(prefix="/api/challenges", tags=["challenges"]) @router.post("", response_model=ChallengeResponse, status_code=status.HTTP_201_CREATED) def create_challenge( challenge: ChallengeCreate, db: Session = Depends(get_db), current_user: User = Depends(auth.get_current_user) ): """Create a new challenge.""" # Calculate next display_order for THIS user max_order = db.query(func.max(Challenge.display_order)).filter( Challenge.user_id == current_user.id ).scalar() new_order = (max_order if max_order is not None else -1) + 1 db_challenge = Challenge(**challenge.dict(), display_order=new_order, user_id=current_user.id) db.add(db_challenge) db.commit() db.refresh(db_challenge) return db_challenge @router.get("", response_model=List[ChallengeResponse]) def read_challenges( db: Session = Depends(get_db), current_user: User = Depends(auth.get_current_user) ): """Get all challenges for the current user.""" challenges = db.query(Challenge).filter( Challenge.user_id == current_user.id ).order_by(Challenge.display_order.asc()).all() return challenges @router.put("/reorder", status_code=status.HTTP_204_NO_CONTENT) def reorder_challenges( ordered_ids: List[int], db: Session = Depends(get_db), current_user: User = Depends(auth.get_current_user) ): """Reorder challenges.""" # Sanity check: ensure these challenges belong to user for index, challenge_id in enumerate(ordered_ids): db.query(Challenge).filter( Challenge.id == challenge_id, Challenge.user_id == current_user.id ).update({"display_order": index}) db.commit() return None @router.delete("/{challenge_id}", status_code=status.HTTP_204_NO_CONTENT) def delete_challenge( challenge_id: int, db: Session = Depends(get_db), current_user: User = Depends(auth.get_current_user) ): """Delete a challenge.""" db_challenge = db.query(Challenge).filter( Challenge.id == challenge_id, Challenge.user_id == current_user.id ).first() if not db_challenge: raise HTTPException(status_code=404, detail="Challenge not found") db.delete(db_challenge) db.commit() return None @router.post("/{challenge_id}/tracking", response_model=TrackingResponse) def log_tracking( challenge_id: int, tracking: TrackingCreate, db: Session = Depends(get_db), current_user: User = Depends(auth.get_current_user) ): """Log tracking for a challenge.""" # Verify challenge belongs to user challenge = db.query(Challenge).filter( Challenge.id == challenge_id, Challenge.user_id == current_user.id ).first() if not challenge: raise HTTPException(status_code=404, detail="Challenge not found") # Check if tracking exists for this date and challenge db_tracking = db.query(Tracking).filter( Tracking.challenge_id == challenge_id, Tracking.date == tracking.date ).first() if db_tracking: db_tracking.reps = tracking.reps db_tracking.completed = tracking.completed db_tracking.notes = tracking.notes else: db_tracking = Tracking(**tracking.dict()) db.add(db_tracking) db.commit() db.refresh(db_tracking) return db_tracking