"""Checksum verification health check for heartbeat monitoring.

Reads the ChecksumRegistry and JSONL telemetry log to surface checksum
verification status per symbol and detect recent failures.
"""

from __future__ import annotations

import json
import logging
import time
from datetime import datetime
from pathlib import Path

logger = logging.getLogger("health-heartbeat")

_TELEMETRY_PATH = Path.home() / ".cache" / "opendeviationbar" / "checksum-telemetry.jsonl"
_FAILURE_WINDOW_S = 24 * 3600  # 24 hours


def check_checksum(results: dict[str, bool | str]) -> None:
    """Populate results dict with checksum verification health data.

    Keys set:
        checksum_ok (bool): True if zero failures in last 24h
        checksum_total_verified (str): total verified count from registry
        checksum_latest (str): latest verified_at from registry summary
        checksum_failures_24h (str): count of failures in last 24h from JSONL
        checksum_failure_details (list[dict]): up to 5 most recent failures
        checksum_per_symbol (dict): per-symbol verified count and last date
    """
    try:
        _check_checksum_inner(results)
    except Exception:
        # Fail-open: don't block heartbeat on registry/telemetry errors
        logger.warning("Checksum health check failed", exc_info=True)
        results["checksum_ok"] = True


def _check_checksum_inner(results: dict[str, bool | str]) -> None:
    """Inner implementation -- exceptions propagate to caller's try/except."""
    try:
        from opendeviationbar.checksum_registry import ChecksumRegistry
    except ImportError:
        logger.warning("ChecksumRegistry not available (ImportError)")
        results["checksum_ok"] = True
        return

    from heartbeat.config import get_heartbeat_symbols

    registry = ChecksumRegistry()
    summary = registry.summary()

    results["checksum_total_verified"] = str(summary["total_verified"])
    results["checksum_latest"] = summary.get("latest_verified_at") or "never"

    # Per-symbol breakdown
    per_symbol: dict[str, dict] = {}
    for symbol in get_heartbeat_symbols():
        records = registry.query_by_symbol(symbol)
        per_symbol[symbol] = {
            "verified": len(records),
            "last_date": records[-1].date if records else None,
        }
    results["checksum_per_symbol"] = per_symbol

    # Scan JSONL telemetry log for recent failures (last 24h)
    failures_24h = _scan_recent_failures()
    results["checksum_failures_24h"] = str(len(failures_24h))
    results["checksum_failure_details"] = failures_24h[:5]  # up to 5 most recent

    # Health gate: any failures in 24h = unhealthy
    results["checksum_ok"] = len(failures_24h) == 0


def _scan_recent_failures() -> list[dict]:
    """Read JSONL telemetry log and return failure entries from last 24h.

    Returns list of dicts sorted by timestamp descending (most recent first).
    """
    if not _TELEMETRY_PATH.exists():
        return []

    cutoff = time.time() - _FAILURE_WINDOW_S
    failures: list[dict] = []

    try:
        with _TELEMETRY_PATH.open() as f:
            for raw_line in f:
                stripped = raw_line.strip()
                if not stripped:
                    continue
                try:
                    entry = json.loads(stripped)
                except json.JSONDecodeError:
                    continue

                event = entry.get("event", "")
                if "fail" not in event:
                    continue

                # Parse timestamp and check if within 24h window
                ts_str = entry.get("timestamp", "")
                try:
                    ts = datetime.fromisoformat(ts_str)
                    if ts.timestamp() >= cutoff:
                        failures.append({
                            "symbol": entry.get("symbol", "?"),
                            "date": entry.get("date", "?"),
                            "expected_hash": entry.get("expected_hash", "?"),
                            "actual_hash": entry.get("actual_hash", "?"),
                        })
                except (ValueError, OSError):
                    continue
    except OSError:
        logger.debug("Could not read telemetry log", exc_info=True)

    # Most recent first
    failures.reverse()
    return failures
