from typing import Optional, List, Dict, Any from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel from app.auth import require_user from app.database import get_db from app.lessons import ( get_user_presets, save_user_preset, delete_user_preset, get_grammar_recommendations, get_curated_articles, record_lesson_session, get_lesson_history, ) from app.ai import generate_lesson_ai_debrief router = APIRouter(tags=["Lessons"]) class SavePresetRequest(BaseModel): name: str steps: List[Dict[str, Any]] icon: Optional[str] = "🚀" description: Optional[str] = "" estimated_min: Optional[int] = 15 class LessonDebriefRequest(BaseModel): preset_name: str duration_seconds: int total_score: int steps: List[Dict[str, Any]] errors: List[Dict[str, Any]] @router.get("/api/lessons/presets") async def api_lessons_get_presets(user: dict = Depends(require_user)): """ Returns available lesson presets (defaults + user-custom). """ with get_db() as conn: presets = get_user_presets(conn, user["id"]) return {"presets": presets} @router.post("/api/lessons/presets") async def api_lessons_save_preset( req: SavePresetRequest, user: dict = Depends(require_user), ): """ Saves a custom user lesson configuration preset. """ if not req.name.strip(): raise HTTPException(status_code=400, detail="Название шаблона не может быть пустым") with get_db() as conn: saved = save_user_preset( conn, user_id=user["id"], name=req.name, steps=req.steps, icon=req.icon or "🚀", description=req.description or "", estimated_min=req.estimated_min or 15, ) return {"status": "ok", "preset": saved} @router.delete("/api/lessons/presets/{preset_id}") async def api_lessons_delete_preset( preset_id: int, user: dict = Depends(require_user), ): """ Deletes a custom user lesson preset. """ with get_db() as conn: deleted = delete_user_preset(conn, user["id"], preset_id) if not deleted: raise HTTPException(status_code=404, detail="Пользовательский шаблон не найден") return {"status": "ok", "deleted": True} @router.get("/api/lessons/grammar-recommendations") async def api_lessons_grammar_recommendations(user: dict = Depends(require_user)): """ Calculates intelligent grammar suggestions: weakest topic, last studied topic, next in syllabus, and full units list. """ with get_db() as conn: recs = get_grammar_recommendations(conn, user["id"]) return recs @router.get("/api/lessons/articles") async def api_lessons_articles( topic: Optional[str] = None, user: dict = Depends(require_user), ): """ Returns curated high-yield reading articles/facts for the lesson reading block. """ articles = get_curated_articles(topic=topic) return {"articles": articles} @router.post("/api/lessons/debrief") async def api_lessons_debrief( req: LessonDebriefRequest, user: dict = Depends(require_user), ): """ Generates a pedagogic AI debrief for the completed lesson session, enriches with historical error context, and records the session. """ # 1. Fetch user error history for pedagogical pattern detection with get_db() as conn: chronic_rows = conn.execute( """ SELECT v.term, count(*) as err_cnt FROM srs_logs l JOIN vocabulary_cards v ON v.id = l.card_id WHERE l.user_id = ? AND l.rating = 1 GROUP BY v.term HAVING err_cnt > 1 ORDER BY err_cnt DESC LIMIT 10 """, (user["id"],), ).fetchall() chronic_vocab = [r["term"] for r in chronic_rows] prog_rows = conn.execute( """ SELECT u.unit_num FROM grammar_progress p JOIN grammar_units u ON u.id = p.unit_id WHERE p.user_id = ? AND p.score < 80 """, (user["id"],), ).fetchall() past_grammar = [r["unit_num"] for r in prog_rows] history_data = { "chronic_vocab_errors": chronic_vocab, "past_grammar_errors": past_grammar, } session_payload = { "preset_name": req.preset_name, "duration_seconds": req.duration_seconds, "total_score": req.total_score, "steps": req.steps, "errors": req.errors, } # 2. Generate AI or deterministic debrief ai_report = await generate_lesson_ai_debrief(session_payload, history_data) # 3. Save completed session to SQLite with get_db() as conn: session_id = record_lesson_session( conn=conn, user_id=user["id"], preset_name=req.preset_name, duration_seconds=req.duration_seconds, total_score=req.total_score, grade=ai_report.get("grade", "A"), steps_summary=req.steps, errors_list=req.errors, ai_report=ai_report, ) return { "session_id": session_id, "ai_report": ai_report, "total_score": req.total_score, "grade": ai_report.get("grade", "A"), } @router.get("/api/lessons/history") async def api_lessons_history( limit: int = 15, user: dict = Depends(require_user), ): """ Returns history of completed comprehensive lessons and overall learning metrics. """ with get_db() as conn: data = get_lesson_history(conn, user["id"], limit=limit) return data