from datetime import datetime, timedelta from fastapi import APIRouter, Depends, Query from sqlalchemy import select, func, and_, case from app.core.database import async_session from app.models.event_log import EventLog from app.api.deps import require_admin router = APIRouter(dependencies=[Depends(require_admin)]) @router.get("/summary") async def get_summary(days: int = Query(default=7, ge=1, le=365)): """ Сводная статистика за последние N дней. Возвращает по каждой группе: - total_commands -- общее количество команд - toggles_on / toggles_off -- включений / выключений - scenes / colors / brightness / temperature -- количество смен режимов - estimated_hours -- оценка часов работы (по парам on/off) """ since = (datetime.now() - timedelta(days=days)).isoformat() async with async_session() as session: # Все события за период result = await session.execute( select(EventLog) .where(EventLog.timestamp >= since) .order_by(EventLog.timestamp) ) events = result.scalars().all() # Агрегация по target_id stats = {} # Для подсчёта часов работы: запоминаем время последнего включения last_on = {} for ev in events: tid = ev.target_id if tid not in stats: stats[tid] = { "target_id": tid, "target_type": ev.target_type, "total_commands": 0, "toggles_on": 0, "toggles_off": 0, "scenes": 0, "colors": 0, "brightness": 0, "temperature": 0, "estimated_hours": 0.0, "by_user": {}, } s = stats[tid] s["total_commands"] += 1 # Счётчик по пользователям u = ev.key_name s["by_user"][u] = s["by_user"].get(u, 0) + 1 # Классификация if ev.action == "toggle_on": s["toggles_on"] += 1 last_on[tid] = ev.timestamp elif ev.action == "toggle_off": s["toggles_off"] += 1 # Считаем время работы if tid in last_on: try: t_on = datetime.fromisoformat(last_on[tid]) t_off = datetime.fromisoformat(ev.timestamp) delta = (t_off - t_on).total_seconds() / 3600.0 # Защита от мусора: макс 24 часа за один сеанс if 0 < delta < 24: s["estimated_hours"] += delta except (ValueError, TypeError): pass del last_on[tid] elif ev.action == "scene": s["scenes"] += 1 elif ev.action == "color": s["colors"] += 1 elif ev.action == "brightness": s["brightness"] += 1 elif ev.action == "temperature": s["temperature"] += 1 # Округляем часы for s in stats.values(): s["estimated_hours"] = round(s["estimated_hours"], 1) return { "period_days": days, "since": since, "groups": list(stats.values()), } @router.get("/log") async def get_log(limit: int = Query(default=50, ge=1, le=500)): """Последние N событий (для просмотра лога).""" async with async_session() as session: result = await session.execute( select(EventLog).order_by(EventLog.timestamp.desc()).limit(limit) ) events = result.scalars().all() return [ { "id": ev.id, "timestamp": ev.timestamp, "key_name": ev.key_name, "action": ev.action, "target_type": ev.target_type, "target_id": ev.target_id, "params": ev.params, } for ev in events ]