from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException, status, Response, Query from sqlalchemy.orm import Session from app.db.database import get_db from app.models.todo import Todo as TodoModel from app.schemas.todo import Todo, TodoCreate, TodoUpdate router = APIRouter() @router.post("/todos", response_model=Todo, status_code=status.HTTP_201_CREATED, summary="Create a new todo") def create_todo(todo: TodoCreate, db: Session = Depends(get_db)): """ Create a new todo item. - **title**: Required title of the todo - **description**: Optional detailed description - **completed**: Whether the todo is completed (defaults to False) Returns the created todo item. """ db_todo = TodoModel(**todo.model_dump()) db.add(db_todo) db.commit() db.refresh(db_todo) return db_todo @router.get("/todos", response_model=List[Todo], summary="Get all todos") def read_todos( skip: int = 0, limit: int = 100, completed: Optional[bool] = Query(None, description="Filter by completion status"), db: Session = Depends(get_db) ): """ Get all todo items with optional filtering. - **skip**: Number of items to skip (pagination) - **limit**: Maximum number of items to return - **completed**: Optional filter by completion status Returns a list of todo items. """ query = db.query(TodoModel) # Apply filter if completed parameter is provided if completed is not None: query = query.filter(TodoModel.completed == completed) todos = query.offset(skip).limit(limit).all() return todos @router.get("/todos/{todo_id}", response_model=Todo, summary="Get a specific todo") def read_todo(todo_id: int, db: Session = Depends(get_db)): """ Get a specific todo item by ID. - **todo_id**: The ID of the todo to retrieve Returns the todo item or raises a 404 if not found. """ db_todo = db.query(TodoModel).filter(TodoModel.id == todo_id).first() if db_todo is None: raise HTTPException(status_code=404, detail="Todo not found") return db_todo @router.put("/todos/{todo_id}", response_model=Todo, summary="Update a todo") def update_todo(todo_id: int, todo: TodoUpdate, db: Session = Depends(get_db)): """ Update a todo item. - **todo_id**: The ID of the todo to update - **todo**: The updated todo data Returns the updated todo item or raises a 404 if not found. """ db_todo = db.query(TodoModel).filter(TodoModel.id == todo_id).first() if db_todo is None: raise HTTPException(status_code=404, detail="Todo not found") # Update fields if provided in the request todo_data = todo.model_dump(exclude_unset=True) for key, value in todo_data.items(): setattr(db_todo, key, value) db.commit() db.refresh(db_todo) return db_todo @router.delete("/todos/{todo_id}", status_code=status.HTTP_204_NO_CONTENT, response_model=None, summary="Delete a todo") def delete_todo(todo_id: int, db: Session = Depends(get_db)): """ Delete a todo item. - **todo_id**: The ID of the todo to delete Returns no content on success or raises a 404 if not found. """ db_todo = db.query(TodoModel).filter(TodoModel.id == todo_id).first() if db_todo is None: raise HTTPException(status_code=404, detail="Todo not found") db.delete(db_todo) db.commit() return Response(status_code=status.HTTP_204_NO_CONTENT)