from __future__ import annotations from datetime import datetime from sqlalchemy.ext.asyncio import AsyncSession from app.core.constants import DeviceStatus from app.core.exceptions import NotFoundException from app.models.mariadb.monitoring import Alert, AlertRule from app.repositories.device_repo import DeviceRepository from app.repositories.monitoring_repo import AlertRepository, AlertRuleRepository from app.schemas.monitoring import AlertRead, AlertRuleCreate, AlertRuleRead, SystemHealthResponse class MonitoringService: def __init__(self, session: AsyncSession): self.alert_rule_repo = AlertRuleRepository(session) self.alert_repo = AlertRepository(session) self.device_repo = DeviceRepository(session) async def create_alert_rule(self, data: AlertRuleCreate, user_id: int) -> AlertRuleRead: rule = AlertRule(**data.model_dump(), created_by=user_id) rule = await self.alert_rule_repo.create(rule) return AlertRuleRead.model_validate(rule) async def list_alert_rules(self) -> list[AlertRuleRead]: rules = await self.alert_rule_repo.get_all() return [AlertRuleRead.model_validate(r) for r in rules] async def list_active_alerts(self, skip: int = 0, limit: int = 50) -> list[AlertRead]: alerts = await self.alert_repo.get_unacknowledged(skip=skip, limit=limit) return [AlertRead.model_validate(a) for a in alerts] async def acknowledge_alert(self, alert_id: int, user_id: int) -> AlertRead: alert = await self.alert_repo.get_by_id(alert_id) if not alert: raise NotFoundException("Alert not found") alert = await self.alert_repo.update(alert, { "is_acknowledged": True, "acknowledged_by": user_id, "acknowledged_at": datetime.utcnow(), }) return AlertRead.model_validate(alert) async def get_system_health(self) -> SystemHealthResponse: active_devices = await self.device_repo.count(filters={"status": DeviceStatus.ONLINE}) active_alerts = await self.alert_repo.count_active() return SystemHealthResponse( status="ok", mariadb="connected", mongodb="connected", redis="connected", mqtt="connected", active_devices=active_devices, active_alerts=active_alerts, )