from fastapi import APIRouter, Depends, HTTPException from app.middleware.auth import get_current_user_id from app.models import AnalyticsSummary from app.services.db import get_pool from app.services.hex_service import run_notebook router = APIRouter(prefix="/analytics", tags=["analytics"]) @router.get("/distractions") async def distraction_analytics(user_id: str = Depends(get_current_user_id)): try: return await run_notebook("distraction_patterns", user_id) except Exception as e: raise HTTPException(status_code=502, detail=f"Hex error: {e}") @router.get("/focus-trends") async def focus_trends(user_id: str = Depends(get_current_user_id)): try: return await run_notebook("focus_trends", user_id) except Exception as e: raise HTTPException(status_code=502, detail=f"Hex error: {e}") @router.get("/weekly-report") async def weekly_report(user_id: str = Depends(get_current_user_id)): try: return await run_notebook("weekly_report", user_id) except Exception as e: raise HTTPException(status_code=502, detail=f"Hex error: {e}") @router.post("/refresh") async def refresh_analytics(user_id: str = Depends(get_current_user_id)): results = {} for key in ("distraction_patterns", "focus_trends", "weekly_report"): try: results[key] = await run_notebook(key, user_id) except Exception as e: results[key] = {"error": str(e)} return results @router.get("/summary", response_model=AnalyticsSummary) async def analytics_summary(user_id: str = Depends(get_current_user_id)): pool = await get_pool() # Direct Postgres queries — no Hex needed focus_minutes = await pool.fetchval( """SELECT COALESCE(SUM(EXTRACT(EPOCH FROM (ended_at - started_at)) / 60), 0) FROM sessions WHERE user_id = $1::uuid AND ended_at IS NOT NULL AND started_at > now() - interval '7 days'""", user_id, ) sessions_completed = await pool.fetchval( """SELECT COUNT(*) FROM sessions WHERE user_id = $1::uuid AND status = 'completed' AND started_at > now() - interval '7 days'""", user_id, ) tasks_completed = await pool.fetchval( """SELECT COUNT(*) FROM tasks WHERE user_id = $1::uuid AND status = 'done' AND updated_at > now() - interval '7 days'""", user_id, ) top_distractors = await pool.fetch( """SELECT app_name, COUNT(*) as count FROM distractions WHERE user_id = $1::uuid AND detected_at > now() - interval '7 days' GROUP BY app_name ORDER BY count DESC LIMIT 5""", user_id, ) avg_attention = await pool.fetchval( """SELECT AVG((checkpoint->>'attention_score')::float) FROM sessions WHERE user_id = $1::uuid AND checkpoint->>'attention_score' IS NOT NULL AND started_at > now() - interval '7 days'""", user_id, ) return AnalyticsSummary( total_focus_minutes=float(focus_minutes or 0), sessions_completed=sessions_completed or 0, tasks_completed=tasks_completed or 0, top_distractors=[{"app_name": r["app_name"], "count": r["count"]} for r in top_distractors], avg_attention_score=float(avg_attention) if avg_attention else None, )