from datetime import datetime from typing import Optional from fastapi import APIRouter, Depends from sqlalchemy import select, func, case from sqlalchemy.ext.asyncio import AsyncSession from app.db.session import get_db from app.models.user import User from app.core.security import get_current_user from app.models.alert import Alert, AlertSeverity, AlertStatus router = APIRouter() @router.get("") async def list_alerts( severity: str = None, status: str = None, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): query = select(Alert) if severity: query = query.where(Alert.severity == AlertSeverity(severity)) if status: query = query.where(Alert.status == AlertStatus(status)) query = query.order_by( case( (Alert.severity == AlertSeverity.CRITICAL, 1), (Alert.severity == AlertSeverity.WARNING, 2), (Alert.severity == AlertSeverity.INFO, 3), ), Alert.created_at.desc(), ) result = await db.execute(query) alerts = result.scalars().all() total_query = select(func.count(Alert.id)) if severity: total_query = total_query.where(Alert.severity == AlertSeverity(severity)) if status: total_query = total_query.where(Alert.status == AlertStatus(status)) total_result = await db.execute(total_query) total = total_result.scalar() return { "total": total, "data": [alert.to_dict() for alert in alerts], } @router.post("/{alert_id}/acknowledge") async def acknowledge_alert( alert_id: int, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): result = await db.execute(select(Alert).where(Alert.id == alert_id)) alert = result.scalar_one_or_none() if not alert: return {"error": "Alert not found"} alert.status = AlertStatus.ACKNOWLEDGED alert.acknowledged_by = current_user.id alert.acknowledged_at = datetime.utcnow() await db.commit() return {"message": "Alert acknowledged", "alert": alert.to_dict()} @router.post("/{alert_id}/resolve") async def resolve_alert( alert_id: int, resolution: str, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): result = await db.execute(select(Alert).where(Alert.id == alert_id)) alert = result.scalar_one_or_none() if not alert: return {"error": "Alert not found"} alert.status = AlertStatus.RESOLVED alert.resolved_by = current_user.id alert.resolved_at = datetime.utcnow() alert.resolution_notes = resolution await db.commit() return {"message": "Alert resolved", "alert": alert.to_dict()} @router.get("/stats") async def get_alert_stats( current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): critical_query = select(func.count(Alert.id)).where( Alert.severity == AlertSeverity.CRITICAL, Alert.status == AlertStatus.ACTIVE, ) warning_query = select(func.count(Alert.id)).where( Alert.severity == AlertSeverity.WARNING, Alert.status == AlertStatus.ACTIVE, ) info_query = select(func.count(Alert.id)).where( Alert.severity == AlertSeverity.INFO, Alert.status == AlertStatus.ACTIVE, ) critical_result = await db.execute(critical_query) warning_result = await db.execute(warning_query) info_result = await db.execute(info_query) return { "critical": critical_result.scalar() or 0, "warning": warning_result.scalar() or 0, "info": info_result.scalar() or 0, }