"""Router per la gestione dello Swipe File. Endpoint: - GET /api/swipe — lista tutte le idee (ordine: piu' recenti prima) - POST /api/swipe — aggiunge una nuova idea - PUT /api/swipe/{item_id} — modifica una voce esistente - DELETE /api/swipe/{item_id} — elimina una voce - POST /api/swipe/{item_id}/mark-used — segna la voce come usata in un calendario """ from __future__ import annotations import logging from fastapi import APIRouter, HTTPException from backend.config import DATA_PATH from backend.schemas.swipe import ( SwipeItem, SwipeItemCreate, SwipeItemUpdate, SwipeListResponse, ) from backend.services.swipe_service import SwipeService logger = logging.getLogger(__name__) router = APIRouter(prefix="/api/swipe", tags=["swipe"]) # SwipeService creato lazily perche' DATA_PATH viene creato nel lifespan di FastAPI _swipe_service: SwipeService | None = None def _get_swipe_service() -> SwipeService: """Ritorna l'istanza SwipeService, creandola al primo accesso. La creazione e' lazy perche' la directory DATA_PATH viene creata durante il lifespan di FastAPI (main.py), non al momento dell'import. """ global _swipe_service if _swipe_service is None: # Assicura che la directory esista (normalmente gia' creata dal lifespan) DATA_PATH.mkdir(parents=True, exist_ok=True) _swipe_service = SwipeService(DATA_PATH) return _swipe_service # --------------------------------------------------------------------------- # Endpoint # --------------------------------------------------------------------------- @router.get("/", response_model=SwipeListResponse) async def list_swipe_items() -> SwipeListResponse: """Lista tutte le idee salvate nello Swipe File. Returns: SwipeListResponse con items ordinati per data creazione (piu' recenti prima). """ items = _get_swipe_service().list_items() return SwipeListResponse(items=items, total=len(items)) @router.post("/", response_model=SwipeItem, status_code=201) async def add_swipe_item(body: SwipeItemCreate) -> SwipeItem: """Aggiunge una nuova idea allo Swipe File. Args: body: SwipeItemCreate con topic (obbligatorio), nicchia e note (opzionali). Returns: SwipeItem creato con id e timestamp generati automaticamente. """ item = _get_swipe_service().add_item(body) logger.info("SwipeItem aggiunto | id=%s | topic=%s", item.id, item.topic[:50]) return item @router.put("/{item_id}", response_model=SwipeItem) async def update_swipe_item(item_id: str, body: SwipeItemUpdate) -> SwipeItem: """Modifica una voce esistente dello Swipe File. Args: item_id: ID della voce da modificare. body: SwipeItemUpdate con i campi da aggiornare (tutti opzionali). Returns: SwipeItem aggiornato. Raises: HTTPException 404: Se la voce non esiste. """ try: item = _get_swipe_service().update_item(item_id, body) logger.info("SwipeItem aggiornato | id=%s", item_id) return item except ValueError as exc: raise HTTPException(status_code=404, detail=str(exc)) from exc @router.delete("/{item_id}") async def delete_swipe_item(item_id: str) -> dict: """Elimina una voce dallo Swipe File. Args: item_id: ID della voce da eliminare. Returns: {"deleted": True} se l'operazione e' riuscita. Raises: HTTPException 404: Se la voce non esiste. """ try: _get_swipe_service().delete_item(item_id) logger.info("SwipeItem eliminato | id=%s", item_id) return {"deleted": True} except ValueError as exc: raise HTTPException(status_code=404, detail=str(exc)) from exc @router.post("/{item_id}/mark-used", response_model=SwipeItem) async def mark_swipe_item_used(item_id: str) -> SwipeItem: """Segna una voce come utilizzata in un calendario generato. Args: item_id: ID della voce da segnare come usata. Returns: SwipeItem aggiornato con used=True. Raises: HTTPException 404: Se la voce non esiste. """ try: item = _get_swipe_service().mark_used(item_id) logger.info("SwipeItem segnato come usato | id=%s", item_id) return item except ValueError as exc: raise HTTPException(status_code=404, detail=str(exc)) from exc