from typing import Optional from fastapi import APIRouter, Depends, Query, Response, status from app.database import get_database, get_redis from app.models.todo import ( TodoCreate, TodoUpdate, TodoResponse, TodoListResponse, BatchRequest, BatchResponse, ToggleResponse, ) from app.services.todo_service import TodoService router = APIRouter(prefix="/api/todos", tags=["todos"]) def _get_service( db=Depends(get_database), redis=Depends(get_redis), ) -> TodoService: return TodoService(db, redis) # 중요: /batch를 /{id} 보다 위에 등록 @router.post("/batch", response_model=BatchResponse) async def batch_action( data: BatchRequest, service: TodoService = Depends(_get_service), ): """F-019~F-021: 일괄 작업 (완료/삭제/카테고리 변경)""" return await service.batch_action(data) @router.get("", response_model=TodoListResponse) async def list_todos( page: int = Query(1, ge=1, description="페이지 번호"), limit: int = Query(20, ge=1, le=100, description="페이지당 항목 수"), completed: Optional[bool] = Query(None, description="완료 상태 필터"), category_id: Optional[str] = Query(None, description="카테고리 필터"), priority: Optional[str] = Query(None, description="우선순위 필터 (high/medium/low)"), tag: Optional[str] = Query(None, description="태그 필터"), sort: str = Query("created_at", description="정렬 기준 (created_at/due_date/priority)"), order: str = Query("desc", description="정렬 방향 (asc/desc)"), service: TodoService = Depends(_get_service), ): """F-002: 할일 목록 조회 (필터/정렬/페이지네이션)""" return await service.list_todos( page=page, limit=limit, completed=completed, category_id=category_id, priority=priority, tag=tag, sort=sort, order=order, ) @router.post("", response_model=TodoResponse, status_code=status.HTTP_201_CREATED) async def create_todo( data: TodoCreate, service: TodoService = Depends(_get_service), ): """F-001: 할일 생성""" return await service.create_todo(data) @router.get("/{todo_id}", response_model=TodoResponse) async def get_todo( todo_id: str, service: TodoService = Depends(_get_service), ): """F-003: 할일 상세 조회""" return await service.get_todo(todo_id) @router.put("/{todo_id}", response_model=TodoResponse) async def update_todo( todo_id: str, data: TodoUpdate, service: TodoService = Depends(_get_service), ): """F-004: 할일 수정""" return await service.update_todo(todo_id, data) @router.delete("/{todo_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_todo( todo_id: str, service: TodoService = Depends(_get_service), ): """F-005: 할일 삭제""" await service.delete_todo(todo_id) return Response(status_code=status.HTTP_204_NO_CONTENT) @router.patch("/{todo_id}/toggle", response_model=ToggleResponse) async def toggle_todo( todo_id: str, service: TodoService = Depends(_get_service), ): """F-006: 할일 완료 토글""" return await service.toggle_todo(todo_id)