"""Junction telemetry check for heartbeat monitoring.

TELEM-03: After sidecar restart, collects diagnostic data about the
REST->WS junction: per-symbol TID deltas (delta=0 means clean handoff).
Purely informational -- NOT health-gating.
"""

from __future__ import annotations

import logging
import subprocess

import requests

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

_SIDECAR_HEALTH_URL = "http://localhost:8081/health"
_SIDECAR_STATUS_URL = "http://localhost:8081/status"


def collect_junction_telemetry(
    results: dict[str, bool | str],
) -> None:
    """Collect junction telemetry from sidecar health/status endpoints.

    Populates results with per-symbol TID deltas:
      junction_delta_{symbol} = ws_first_tid - rest_last_tid - 1
        (0 = clean handoff, >0 = gap, <0 = overlap)
      junction_detail_{symbol} = human-readable detail (only when delta != 0)
      junction_available = True/False

    Falls back to journalctl logs if HTTP endpoints don't provide data.
    """
    try:
        resp = requests.get(_SIDECAR_HEALTH_URL, timeout=5)
        if resp.status_code != 200:
            results["junction_available"] = False
            return

        health_data = resp.json()

        # Try status endpoint for more detailed data
        status_data = {}
        try:
            status_resp = requests.get(_SIDECAR_STATUS_URL, timeout=5)
            if status_resp.status_code == 200:
                status_data = status_resp.json()
        except Exception:
            logger.debug("sidecar /status endpoint unavailable", exc_info=True)

        # Extract from health or status data (per-symbol)
        symbols_data = (
            status_data.get("symbols")
            or health_data.get("symbols")
            or {}
        )

        has_any_data = False
        if symbols_data:
            for sym, sym_data in symbols_data.items():
                if not isinstance(sym_data, dict):
                    continue
                r_tid = sym_data.get("rest_last_tid")
                w_tid = sym_data.get("ws_first_tid")
                if r_tid is not None and w_tid is not None:
                    has_any_data = True
                    delta = int(w_tid) - int(r_tid) - 1
                    results[f"junction_delta_{sym}"] = delta
                    if delta != 0:
                        results[f"junction_detail_{sym}"] = (
                            f"rest={r_tid}, ws={w_tid}, delta={delta}"
                        )
                elif r_tid is not None or w_tid is not None:
                    has_any_data = True
                    results[f"junction_delta_{sym}"] = "partial"
                    results[f"junction_detail_{sym}"] = (
                        f"rest={r_tid}, ws={w_tid}"
                    )

        # If HTTP didn't give us per-symbol data, try journal logs
        if not has_any_data:
            _try_journal_fallback(results)

        results["junction_available"] = True

    except (requests.ConnectionError, requests.Timeout, OSError):
        logger.debug("sidecar unavailable for junction telemetry", exc_info=True)
        results["junction_available"] = False


def _try_journal_fallback(
    results: dict[str, bool | str],
) -> None:
    """Parse sidecar journal logs for junction data as fallback.

    Journal logs provide aggregate data only (not per-symbol deltas),
    so we mark junction_available as 'journal_only' for the formatter
    to display a note.
    """
    try:
        r = subprocess.run(
            [
                "journalctl",
                "--user",
                "-u",
                "opendeviationbar-sidecar",
                "--since",
                "30 min ago",
                "--no-pager",
                "-o",
                "short-precise",
            ],
            capture_output=True,
            text=True,
            timeout=10,
            check=False,
        )
        if r.returncode != 0:
            return

        found_rest = False
        found_ws = False
        for line in reversed(r.stdout.splitlines()):
            if not found_rest and "fill_from_rest" in line and "last_tid=" in line:
                found_rest = True
            if not found_ws and "ws_first_tid=" in line:
                found_ws = True

        if found_rest or found_ws:
            # Journal has some data but not per-symbol deltas
            results["junction_available"] = "journal_only"

    except (FileNotFoundError, subprocess.TimeoutExpired, OSError):
        logger.debug("journalctl fallback failed", exc_info=True)
