from fastapi import APIRouter, Depends, HTTPException, status, Query from sqlalchemy.orm import Session from typing import List, Optional, Dict, Any from datetime import datetime from app import crud from app.models.todo import PriorityEnum as ModelPriorityEnum from app.schemas.todo import Todo, TodoCreate, TodoUpdate, PriorityEnum from app.db.base import get_db router = APIRouter() @router.get("/", response_model=List[Todo]) def read_todos( skip: int = 0, limit: int = 100, category: Optional[str] = None, priority: Optional[PriorityEnum] = None, completed: Optional[bool] = None, due_before: Optional[datetime] = None, due_after: Optional[datetime] = None, search: Optional[str] = None, sort_by: str = "created_at", sort_desc: bool = True, db: Session = Depends(get_db) ): """ Get all todos with filtering options: - Filter by category - Filter by priority level - Filter by completion status - Filter by due date (before/after) - Search in title and description - Sort by any field - Pagination """ todos = crud.get_todos( db=db, skip=skip, limit=limit, category=category, priority=priority.value if priority else None, completed=completed, due_before=due_before, due_after=due_after, search=search, sort_by=sort_by, sort_desc=sort_desc ) return todos @router.post("/", response_model=Todo, status_code=status.HTTP_201_CREATED) def create_todo(todo: TodoCreate, db: Session = Depends(get_db)): """Create a new todo item with extended fields""" return crud.create_todo(db=db, todo=todo) @router.get("/search", response_model=List[Todo]) def search_todos( q: str = Query(..., min_length=1, description="Search query for title or description"), skip: int = 0, limit: int = 100, sort_by: str = "created_at", sort_desc: bool = True, db: Session = Depends(get_db) ): """ Search todos by title or description content Returns todos where the title or description contains the search query """ todos = crud.get_todos( db=db, skip=skip, limit=limit, search=q, sort_by=sort_by, sort_desc=sort_desc ) return todos @router.get("/stats", response_model=Dict[str, Any]) def get_todo_stats(db: Session = Depends(get_db)): """Get statistics about todos including: - Total, completed, and incomplete counts - Number of overdue tasks - Number of tasks completed in the last 24 hours - Number of tasks completed in the last 7 days - Breakdown by category and priority """ return crud.get_todo_stats(db=db) @router.get("/{todo_id}", response_model=Todo) def read_todo(todo_id: int, db: Session = Depends(get_db)): """Get a specific todo by ID""" db_todo = crud.get_todo(db, todo_id=todo_id) if db_todo is None: raise HTTPException(status_code=404, detail="Todo not found") return db_todo @router.put("/{todo_id}", response_model=Todo) def update_todo(todo_id: int, todo: TodoUpdate, db: Session = Depends(get_db)): """Update a todo with new values including category, priority, due date and completion status. When a todo is marked as completed, the completion_date will be automatically set to the current time if not explicitly provided. If a todo is marked as not completed, the completion_date will be cleared. """ db_todo = crud.update_todo(db=db, todo_id=todo_id, todo=todo) if db_todo is None: raise HTTPException(status_code=404, detail="Todo not found") return db_todo @router.delete("/{todo_id}", status_code=status.HTTP_204_NO_CONTENT) def delete_todo(todo_id: int, db: Session = Depends(get_db)): """Delete a todo by ID""" success = crud.delete_todo(db=db, todo_id=todo_id) if not success: raise HTTPException(status_code=404, detail="Todo not found") return None