from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Query from pydantic import BaseModel from app.auth import require_user from app.database import get_db from app.cefr import ( get_cefr_level_summaries, get_cefr_quiz_batch, process_cefr_answer, reset_user_cefr_level, ingest_cefr_word, ) router = APIRouter(tags=["CEFR Testing & Mining"]) class CefrAnswerRequest(BaseModel): question_id: int selected_option: str class CefrResetRequest(BaseModel): level: str class CefrAddWordRequest(BaseModel): level: str term: str context_sentence: Optional[str] = "" @router.get("/api/cefr/levels") async def api_cefr_levels(user: dict = Depends(require_user)): """ Returns progress summaries for all CEFR levels (A1, A2, B1, B2). """ with get_db() as conn: summaries = get_cefr_level_summaries(conn, user["id"]) return {"levels": summaries} @router.get("/api/cefr/quiz") async def api_cefr_quiz( level: str = Query("A1"), count: int = Query(10, ge=1, le=30), mode: str = Query("all"), user: dict = Depends(require_user), ): """ Returns next batch of Cloze Tap test questions for level (A1..B2). """ with get_db() as conn: quiz_items = get_cefr_quiz_batch(conn, user["id"], level, count, mode) return {"level": level.upper(), "count": len(quiz_items), "quiz": quiz_items} @router.post("/api/cefr/answer") async def api_cefr_answer( req: CefrAnswerRequest, user: dict = Depends(require_user), ): """ Submits an answer for a CEFR question. If wrong, automatically ingests into user's SRS active vocabulary with status 'learning'. """ with get_db() as conn: result = process_cefr_answer(conn, user["id"], req.question_id, req.selected_option) if "error" in result: raise HTTPException(status_code=404, detail=result["error"]) return result @router.post("/api/cefr/reset") async def api_cefr_reset( req: CefrResetRequest, user: dict = Depends(require_user), ): """ Resets user testing progress for a given CEFR level. """ with get_db() as conn: deleted = reset_user_cefr_level(conn, user["id"], req.level) return {"status": "ok", "level": req.level.upper(), "reset_count": deleted} @router.post("/api/cefr/add-word") async def api_cefr_add_word( req: CefrAddWordRequest, user: dict = Depends(require_user), ): """ Adds a word from a CEFR test options list directly into user's SRS active vocabulary. """ with get_db() as conn: return ingest_cefr_word(conn, user["id"], req.level, req.term, req.context_sentence)