"""Sleep log management router.""" from typing import Annotated from fastapi import APIRouter, HTTPException, Depends from baby_monitor.models.sleep import ( CreateSleepRequest, UpdateSleepRequest, SleepResponse, ) from baby_monitor.routers.auth import verify_token from baby_monitor.repositories.interfaces import ( SleepRepositoryInterface, ChildRepositoryInterface, ) from baby_monitor.repositories.dependencies import ( get_sleep_repository, get_child_repository, ) from baby_monitor.utils import verify_child_access router = APIRouter(prefix="/api/sleep", tags=["sleep"]) @router.post("", response_model=SleepResponse, status_code=201) def create_sleep( request: CreateSleepRequest, user_id: Annotated[int, Depends(verify_token)], sleep_repo: Annotated[SleepRepositoryInterface, Depends(get_sleep_repository)], child_repo: Annotated[ChildRepositoryInterface, Depends(get_child_repository)], ) -> SleepResponse: """Create a new sleep log entry.""" # Verify the child belongs to the authenticated user verify_child_access(child_repo, request.child_id, user_id) sleep = sleep_repo.create( child_id=request.child_id, start_time=request.start_time, end_time=request.end_time, ) return SleepResponse(**sleep) @router.get("/active", response_model=SleepResponse | None) def get_active_sleep( user_id: Annotated[int, Depends(verify_token)], sleep_repo: Annotated[SleepRepositoryInterface, Depends(get_sleep_repository)], child_repo: Annotated[ChildRepositoryInterface, Depends(get_child_repository)], ) -> SleepResponse | None: """Get the current active sleep (where end_time is null) for the user.""" sleeps = sleep_repo.get_by_user_id(user_id) # Find the first sleep with no end_time for sleep in sleeps: if sleep["end_time"] is None: # Get child info to include in response child = child_repo.get_by_id(sleep["child_id"]) response_data = sleep.copy() if child: response_data["child_name"] = child["name"] return SleepResponse(**response_data) return None @router.get("", response_model=list[SleepResponse]) def get_user_sleeps( user_id: Annotated[int, Depends(verify_token)], sleep_repo: Annotated[SleepRepositoryInterface, Depends(get_sleep_repository)], ) -> list[SleepResponse]: """Get all sleep logs for the authenticated user's children.""" sleeps = sleep_repo.get_by_user_id(user_id) return [SleepResponse(**sleep) for sleep in sleeps] @router.get("/{sleep_id}", response_model=SleepResponse) def get_sleep( sleep_id: int, user_id: Annotated[int, Depends(verify_token)], sleep_repo: Annotated[SleepRepositoryInterface, Depends(get_sleep_repository)], child_repo: Annotated[ChildRepositoryInterface, Depends(get_child_repository)], ) -> SleepResponse: """Get a specific sleep log by ID.""" sleep = sleep_repo.get_by_id(sleep_id) if not sleep: raise HTTPException(status_code=404, detail="Sleep log not found") # Verify the sleep belongs to user's child verify_child_access(child_repo, sleep["child_id"], user_id) return SleepResponse(**sleep) @router.put("/{sleep_id}", response_model=SleepResponse) def update_sleep( sleep_id: int, request: UpdateSleepRequest, user_id: Annotated[int, Depends(verify_token)], sleep_repo: Annotated[SleepRepositoryInterface, Depends(get_sleep_repository)], child_repo: Annotated[ChildRepositoryInterface, Depends(get_child_repository)], ) -> SleepResponse: """Update an existing sleep log.""" sleep = sleep_repo.get_by_id(sleep_id) if not sleep: raise HTTPException(status_code=404, detail="Sleep log not found") # Verify the sleep belongs to user's child verify_child_access(child_repo, sleep["child_id"], user_id) updated = sleep_repo.update( sleep_id=sleep_id, end_time=request.end_time, ) if not updated: raise HTTPException(status_code=500, detail="Failed to update sleep log") return SleepResponse(**updated) @router.delete("/{sleep_id}", status_code=204) def delete_sleep( sleep_id: int, user_id: Annotated[int, Depends(verify_token)], sleep_repo: Annotated[SleepRepositoryInterface, Depends(get_sleep_repository)], child_repo: Annotated[ChildRepositoryInterface, Depends(get_child_repository)], ) -> None: """Delete a sleep log.""" sleep = sleep_repo.get_by_id(sleep_id) if not sleep: raise HTTPException(status_code=404, detail="Sleep log not found") # Verify the sleep belongs to user's child verify_child_access(child_repo, sleep["child_id"], user_id) success = sleep_repo.delete(sleep_id) if not success: raise HTTPException(status_code=500, detail="Failed to delete sleep log")