"""Smoke checks for deployed Prometheus + Alertmanager routing."""

from __future__ import annotations

from dataclasses import dataclass
from datetime import UTC, datetime, timedelta

import httpx


@dataclass
class AlertSmokeResult:
    name: str
    ok: bool
    detail: str


def run_alert_smoke_check(
    prometheus_url: str,
    alertmanager_url: str,
    *,
    send_test_alert: bool = False,
    alert_name: str = "HiveManualSmoke",
    ttl_seconds: int = 180,
) -> list[AlertSmokeResult]:
    """Run smoke checks against deployed monitoring surfaces."""
    prom_base = prometheus_url.rstrip("/")
    alert_base = alertmanager_url.rstrip("/")

    with httpx.Client(timeout=10) as client:
        results = [
            _check_prometheus_targets(client, prom_base),
            _check_prometheus_rules(client, prom_base),
            _check_alertmanager_ready(client, alert_base),
        ]

        if send_test_alert:
            results.append(_post_synthetic_alert(client, alert_base, alert_name=alert_name, ttl_seconds=ttl_seconds))
            results.append(_check_synthetic_alert_visible(client, alert_base, alert_name=alert_name))

    return results


def _check_prometheus_targets(client: httpx.Client, prom_base: str) -> AlertSmokeResult:
    try:
        resp = client.get(f"{prom_base}/api/v1/targets")
        if resp.status_code != 200:
            return AlertSmokeResult("prometheus_targets", False, f"HTTP {resp.status_code}")
        targets = resp.json().get("data", {}).get("activeTargets", [])
        hive_targets = [target for target in targets if target.get("labels", {}).get("job") == "hivecompute"]
        if not hive_targets:
            return AlertSmokeResult("prometheus_targets", False, "No active hivecompute scrape targets found")
        unhealthy = [target for target in hive_targets if target.get("health") != "up"]
        if unhealthy:
            return AlertSmokeResult("prometheus_targets", False, "Hivecompute target exists but is not healthy")
        return AlertSmokeResult("prometheus_targets", True, "hivecompute target is up")
    except Exception as exc:
        return AlertSmokeResult("prometheus_targets", False, f"Connection failed: {exc}")


def _check_prometheus_rules(client: httpx.Client, prom_base: str) -> AlertSmokeResult:
    try:
        resp = client.get(f"{prom_base}/api/v1/rules")
        if resp.status_code != 200:
            return AlertSmokeResult("prometheus_rules", False, f"HTTP {resp.status_code}")
        groups = resp.json().get("data", {}).get("groups", [])
        hive_groups = [group for group in groups if str(group.get("name", "")).startswith("hivecompute")]
        if not hive_groups:
            return AlertSmokeResult("prometheus_rules", False, "No hivecompute rule groups loaded")
        return AlertSmokeResult("prometheus_rules", True, f"{len(hive_groups)} hivecompute rule group(s) loaded")
    except Exception as exc:
        return AlertSmokeResult("prometheus_rules", False, f"Connection failed: {exc}")


def _check_alertmanager_ready(client: httpx.Client, alert_base: str) -> AlertSmokeResult:
    try:
        resp = client.get(f"{alert_base}/-/ready")
        if resp.status_code != 200:
            return AlertSmokeResult("alertmanager_ready", False, f"HTTP {resp.status_code}")
        return AlertSmokeResult("alertmanager_ready", True, "Alertmanager is ready")
    except Exception as exc:
        return AlertSmokeResult("alertmanager_ready", False, f"Connection failed: {exc}")


def _post_synthetic_alert(
    client: httpx.Client,
    alert_base: str,
    *,
    alert_name: str,
    ttl_seconds: int,
) -> AlertSmokeResult:
    try:
        now = datetime.now(UTC)
        ends_at = now + timedelta(seconds=max(ttl_seconds, 60))
        payload = [
            {
                "labels": {
                    "alertname": alert_name,
                    "severity": "page",
                    "service": "hivecompute",
                    "smoke": "true",
                },
                "annotations": {
                    "summary": "Manual alert smoke test",
                    "description": "Synthetic alert posted by scripts/smoke_alerting.py to verify routing.",
                },
                "startsAt": now.isoformat(),
                "endsAt": ends_at.isoformat(),
            }
        ]
        resp = client.post(f"{alert_base}/api/v2/alerts", json=payload)
        if resp.status_code not in {200, 201, 202}:
            return AlertSmokeResult("post_test_alert", False, f"HTTP {resp.status_code}")
        return AlertSmokeResult("post_test_alert", True, f"Posted synthetic alert '{alert_name}'")
    except Exception as exc:
        return AlertSmokeResult("post_test_alert", False, f"Post failed: {exc}")


def _check_synthetic_alert_visible(client: httpx.Client, alert_base: str, *, alert_name: str) -> AlertSmokeResult:
    try:
        resp = client.get(f"{alert_base}/api/v2/alerts")
        if resp.status_code != 200:
            return AlertSmokeResult("synthetic_alert_visible", False, f"HTTP {resp.status_code}")
        alerts = resp.json()
        for alert in alerts:
            if alert.get("labels", {}).get("alertname") == alert_name:
                return AlertSmokeResult("synthetic_alert_visible", True, f"'{alert_name}' is active in Alertmanager")
        return AlertSmokeResult("synthetic_alert_visible", False, f"'{alert_name}' not found in Alertmanager")
    except Exception as exc:
        return AlertSmokeResult("synthetic_alert_visible", False, f"Connection failed: {exc}")


def format_results(results: list[AlertSmokeResult]) -> str:
    passed = sum(1 for result in results if result.ok)
    lines = [f"Alert smoke: {passed}/{len(results)} passed"]
    for result in results:
        status = "PASS" if result.ok else "FAIL"
        lines.append(f"  [{status}] {result.name}: {result.detail}")
    return "\n".join(lines)


def manual_follow_up_checklist(alertmanager_url: str, alert_name: str) -> list[str]:
    return [
        f"Confirm the configured staging email receiver got the '{alert_name}' notification.",
        (
            f"Open {alertmanager_url.rstrip('/')}/#/alerts and verify the synthetic alert "
            "appears, then resolves after its TTL."
        ),
        "After the alert resolves, confirm no lingering silences or grouped alerts are hiding future pages.",
    ]


def troubleshooting_hints(results: list[AlertSmokeResult]) -> list[str]:
    failed = {result.name for result in results if not result.ok}
    hints: list[str] = []

    if "prometheus_targets" in failed:
        hints.append("Check Prometheus target discovery and confirm the hivecompute scrape target is healthy.")
    if "prometheus_rules" in failed:
        hints.append("Confirm prometheus/prometheus.yml is loading alerts.yml and the rule groups have reloaded.")
    if "alertmanager_ready" in failed:
        hints.append("Check Alertmanager startup logs and config expansion for SMTP-related failures.")
    if "post_test_alert" in failed or "synthetic_alert_visible" in failed:
        hints.append(
            "Check Alertmanager API reachability and whether the synthetic alert labels match "
            "the configured routes."
        )
    if not hints:
        hints.append("Check Prometheus and Alertmanager logs for the deploy you are validating.")
    return hints
