"""Yesterday orphan completion check for heartbeat monitoring.

TELEM-02: Per-symbol validation that yesterday's orphan bar closes
at exactly crossover_tid - 1 (the last trade of the previous day).
"""

from __future__ import annotations

import logging
from datetime import datetime, timezone

from heartbeat.config import HEARTBEAT_PRIORITY_SYMBOLS

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


def _get_midnight_crossover_tid(symbol: str) -> int | None:
    """Query Binance REST for the first aggregated trade at or after UTC midnight.

    Returns the agg_trade_id of the first trade of today, or None on failure.
    Uses raw HTTP (no PyO3 binding) so heartbeat stays independent of the wheel.
    """
    import requests

    midnight_ms = int(
        datetime.now(timezone.utc)
        .replace(hour=0, minute=0, second=0, microsecond=0)
        .timestamp()
        * 1000
    )

    try:
        resp = requests.get(
            "https://api.binance.com/api/v3/aggTrades",
            params={
                "symbol": symbol,
                "startTime": str(midnight_ms),
                "endTime": str(midnight_ms + 1000),
                "limit": "1",
            },
            timeout=10,
        )
        resp.raise_for_status()
        result = resp.json()
    except Exception:
        logger.warning(
            "midnight crossover query failed for %s (midnight_ms=%d)",
            symbol,
            midnight_ms,
            exc_info=True,
        )
        return None

    if not result:
        logger.warning(
            "no trades found at midnight for %s (midnight_ms=%d)", symbol, midnight_ms
        )
        return None

    return int(result[0]["a"])


def collect_yesterday_completion(
    client: object,  # clickhouse_connect Client
    results: dict[str, bool | str],
) -> None:
    """Check yesterday's orphan bar completion per streaming symbol.

    For each symbol in HEARTBEAT_PRIORITY_SYMBOLS:
    1. Get midnight crossover TID (first trade of today)
    2. Query yesterday's orphan bar from ClickHouse
    3. Compare: orphan.last_agg_trade_id should == crossover_tid - 1
    """
    from opendeviationbar.clickhouse.stathera_query import FULL_TABLE

    checked_symbols: list[str] = []

    for symbol in HEARTBEAT_PRIORITY_SYMBOLS:
        checked_symbols.append(symbol)

        # Step 1: Get crossover TID
        crossover_tid = _get_midnight_crossover_tid(symbol)
        if crossover_tid is None:
            results[f"yesterday_{symbol}"] = "query_failed"
            continue

        # Step 2: Query yesterday's LAST bar (the orphan — last bar before midnight)
        # No is_orphan column in CH; orphan = last bar of the day by trade ID
        try:
            row = client.query(  # type: ignore[union-attr]
                f"""
                SELECT max(last_agg_trade_id)
                FROM {FULL_TABLE} FINAL
                WHERE symbol = '{symbol}'
                  AND toDate(open_time_ms / 1000) = yesterday()
                  AND last_agg_trade_id > 0
                """
            )
        except Exception:
            logger.warning(
                "yesterday orphan query failed for %s", symbol, exc_info=True
            )
            results[f"yesterday_{symbol}"] = "query_failed"
            continue

        # Step 3: Compare
        orphan_tid = row.result_rows[0][0] if row.result_rows else None
        if orphan_tid is None:
            results[f"yesterday_{symbol}"] = "no_orphan"
        else:
            expected = crossover_tid - 1
            if orphan_tid == expected:
                results[f"yesterday_{symbol}"] = True
                results[f"yesterday_{symbol}_detail"] = "clean"
            else:
                results[f"yesterday_{symbol}"] = False
                results[f"yesterday_{symbol}_detail"] = (
                    f"expected {expected}, got {orphan_tid}"
                )

    # Aggregate health gate: True unless a real mismatch (False) is detected
    results["yesterday_completion"] = all(
        results.get(f"yesterday_{s}") is not False for s in checked_symbols
    )
