"""Watch probe alert linkage — reuse agent threshold detection."""

from __future__ import annotations

import logging
from typing import Any

from server.api.agent import REDIS_ALERT_KEY_PREFIX, _alert_metric_key, _detect_alerts, _detect_recovery
from server.api.websocket import broadcast_alert, broadcast_recovery
from server.config import settings
from server.infrastructure.redis.client import get_redis
from server.utils.watch_metrics import PROBE_OK, WatchProbeSample

logger = logging.getLogger("nexus.watch_alerts")


def _sample_to_system_info(sample: WatchProbeSample) -> dict[str, Any]:
    return {
        "cpu_usage": sample.cpu_pct,
        "mem_usage": sample.mem_pct,
        "disk_usage": sample.disk_pct,
    }


async def process_watch_probe_alerts(
    *,
    server_id: int,
    server_name: str,
    sample: WatchProbeSample,
) -> None:
    """Fire alert/recovery broadcasts when pinned-server probe exceeds thresholds."""
    if sample.probe_status != PROBE_OK:
        return

    system_info = _sample_to_system_info(sample)
    thresholds = {
        "cpu": settings.CPU_ALERT_THRESHOLD,
        "mem": settings.MEM_ALERT_THRESHOLD,
        "disk": settings.DISK_ALERT_THRESHOLD,
    }

    redis = get_redis()
    alert_key = f"{REDIS_ALERT_KEY_PREFIX}{server_id}"

    alerts = _detect_alerts(system_info, thresholds)
    for alert_type, alert_value in alerts:
        logger.warning("Watch alert: server %s %s=%s%%", server_id, alert_type, alert_value)
        await broadcast_alert(server_id, alert_type, alert_value, server_name)
        try:
            await redis.sadd(alert_key, alert_type)
            await redis.expire(alert_key, 3600)
        except Exception:
            logger.debug("Failed to track watch alert in Redis for server %s", server_id, exc_info=True)

    try:
        prev_alerts = await redis.smembers(alert_key)
        if prev_alerts:
            recoveries = _detect_recovery(system_info, prev_alerts, thresholds)
            for metric, value in recoveries:
                logger.info("Watch recovery: server %s %s=%s%%", server_id, metric, value)
                await broadcast_recovery(server_id, metric, value, server_name)
                for prev in prev_alerts:
                    if _alert_metric_key(prev) == metric:
                        await redis.srem(alert_key, prev)
    except Exception:
        logger.debug("Watch recovery detection failed for server %s", server_id, exc_info=True)
