"""Workout day viewer routes. Displays the warmup routine and main exercises for each workout day, with the active profile's programming targets. """ from datetime import date import structlog from fastapi import APIRouter, Depends, Request from fastapi.responses import HTMLResponse from sqlmodel import Session, select from app.database import get_db_session from app.models.user import User from app.models.user_exercise_program import UserExerciseProgram from app.models.workout_day import WorkoutDay from app.services.exercise_service import ExerciseService from app.services.log_service import LogService from app.services.progression_service import ProgressionService from app.services.workout_session_service import WorkoutSessionService from app.utils.auth import require_active_profile, get_active_profile_id logger = structlog.get_logger(__name__) router = APIRouter(prefix="/workouts", tags=["workouts"]) @router.get("", response_class=HTMLResponse) async def workout_days_list( request: Request, session: Session = Depends(get_db_session), profile: User = Depends(require_active_profile), ): """List all workout days with a recommendation for what to do next.""" exercise_service = ExerciseService(session) days = exercise_service.list_workout_days() ws_service = WorkoutSessionService(session) last_session = ws_service.get_last_completed_session(profile.id) recommended_day_id = None last_workout_name = None last_workout_date = None if last_session: last_day = session.get(WorkoutDay, last_session.workout_day_id) if last_day: last_workout_name = last_day.name last_workout_date = last_session.date next_day_number = (last_day.day_number % 4) + 1 for d in days: if d.day_number == next_day_number: recommended_day_id = d.id break else: for d in days: if d.day_number == 1: recommended_day_id = d.id break templates = request.app.state.templates return templates.TemplateResponse("pages/workout_days.html", { "request": request, "days": days, "recommended_day_id": recommended_day_id, "last_workout_name": last_workout_name, "last_workout_date": last_workout_date, }) @router.get("/{day_name}", response_class=HTMLResponse) async def workout_day_detail( day_name: str, request: Request, session: Session = Depends(get_db_session), profile: User = Depends(require_active_profile), ): """Display a full workout day -- warmups + exercises with form cues.""" exercise_service = ExerciseService(session) # Normalize day name for DB lookup (e.g., "push" -> "Push", "full-body" -> "Full Body") day_display = day_name.replace("-", " ").title() warmups = exercise_service.list_warmups() exercises = exercise_service.list_exercises(workout_day=day_display) # Get active profile's programming active_profile_id = profile.id programs = {} existing_logs = {} statement = select(UserExerciseProgram).where( UserExerciseProgram.user_id == active_profile_id ) for prog in session.exec(statement).all(): programs[prog.exercise_id] = prog # Look up the workout day ID for logging forms days = exercise_service.list_workout_days() workout_day_id = 0 for d in days: if d.name == day_display: workout_day_id = d.id break # Get progression suggestions for each exercise suggestions = {} progression = ProgressionService(session) for exercise in exercises: suggestions[exercise.id] = progression.get_suggestion( active_profile_id, exercise.id, ) # Load existing logs for today's session (if any) if workout_day_id: ws_service = WorkoutSessionService(session) ws = ws_service.get_or_create_session( user_id=active_profile_id, workout_day_id=workout_day_id, session_date=date.today(), ) log_service = LogService(session) all_logs = log_service.list_logs_for_session(ws.id) for log in all_logs: existing_logs.setdefault(log.exercise_id, []).append(log) templates = request.app.state.templates return templates.TemplateResponse("pages/workout_day.html", { "request": request, "day_name": day_display, "warmups": warmups, "exercises": exercises, "programs": programs, "active_profile": profile, "existing_logs": existing_logs, "suggestions": suggestions, "workout_day_id": workout_day_id, })