from __future__ import annotations import asyncio import logging from fastapi import APIRouter, Depends from app.api.auth import get_current_user_id from app.api.schemas import WordCreate, WordResponse from app.db.session import get_session_factory from app.pipelines.define import define_word from app.services.dictionary import delete_word, list_words, save_word from app.services.user import get_or_create_user router = APIRouter(prefix="/words", tags=["dictionary"]) log = logging.getLogger(__name__) async def _fill_meaning(user_id: int, word: str, level: str, lang: str = "ru") -> None: """Generate and store a definition for a word saved without one (background).""" meaning = await define_word(word, level, lang) if not meaning: return factory = get_session_factory() async with factory() as s: await save_word(s, user_id, word, meaning) log.info("auto-defined word %r for user %s", word, user_id) @router.get("", response_model=list[WordResponse]) async def get_words(user_id: int = Depends(get_current_user_id)) -> list[WordResponse]: """List saved words.""" factory = get_session_factory() async with factory() as s: words = await list_words(s, user_id) return [WordResponse(word=w.word, meaning=w.meaning, created_at=w.created_at) for w in words] @router.post("", response_model=dict[str, str]) async def add_word( body: WordCreate, user_id: int = Depends(get_current_user_id), ) -> dict[str, str]: """Save a word. If no meaning is given, save instantly and fill a definition in the background.""" word = body.word.lower().strip() context = body.context.strip() if body.context else None meaning = body.meaning.strip() if body.meaning else None factory = get_session_factory() async with factory() as s: user = await get_or_create_user(s, user_id) await save_word(s, user_id, word, meaning or "", context) if not meaning: asyncio.create_task(_fill_meaning(user_id, word, user.level, user.interface_language)) return {"status": "saved"} @router.delete("/{word}") async def remove_word( word: str, user_id: int = Depends(get_current_user_id), ) -> dict[str, bool]: """Delete a word from dictionary.""" factory = get_session_factory() async with factory() as s: deleted = await delete_word(s, user_id, word) return {"deleted": deleted}