"""Atomic observation queries for Claude Code CLI monitoring.

Run via: ``mise run observe:day-mode`` or Claude Code ``/loop 5m`` post-deploy.
Each observation returns (name, passed: bool, detail: str).
"""

from __future__ import annotations

import logging
from typing import TYPE_CHECKING, NamedTuple

if TYPE_CHECKING:
    import clickhouse_connect.driver

    from opendeviationbar.config.kintsugi import KintsugiConfig

from .oracle import cross_midnight_count_global, stathera_day_classification

logger = logging.getLogger(__name__)


def _kintsugi_cfg() -> KintsugiConfig:
    from opendeviationbar.config.kintsugi import KintsugiConfig
    return KintsugiConfig()


class ObservationResult(NamedTuple):
    name: str
    passed: bool
    detail: str


def observe_zero_cross_midnight(client: clickhouse_connect.driver.Client) -> ObservationResult:
    """OBSERVATION 1: Zero cross-midnight bars (atomic invariant)."""
    count = cross_midnight_count_global(client)
    return ObservationResult(
        name="cross_midnight_zero",
        passed=(count == 0),
        detail=f"violations={count} (expected 0)",
    )


def observe_kintsugi_convergence(client: clickhouse_connect.driver.Client) -> ObservationResult:
    """OBSERVATION 2: Kintsugi repair rate trending toward zero."""
    result = client.query("""
        SELECT toDate(repaired_at) AS day, count() AS repairs, sum(bars_written) AS bars
        FROM opendeviationbar_cache.kintsugi_log
        GROUP BY day ORDER BY day DESC LIMIT 3
    """)
    rows = result.result_rows
    if not rows:
        return ObservationResult("kintsugi_convergence", True, "no repairs logged")
    latest_repairs = rows[0][1]
    return ObservationResult(
        name="kintsugi_convergence",
        passed=(latest_repairs < _kintsugi_cfg().convergence_max_repairs_per_day),
        detail=f"latest_day={rows[0][0]}, repairs={latest_repairs}, bars={rows[0][2]}",
    )


def observe_ouroboros_mode(client: clickhouse_connect.driver.Client) -> ObservationResult:
    """OBSERVATION 3: kintsugi_log writes ouroboros_mode='day'."""
    result = client.query("""
        SELECT ouroboros_mode, count() AS n
        FROM opendeviationbar_cache.kintsugi_log
        GROUP BY ouroboros_mode
    """)
    modes = {row[0]: row[1] for row in result.result_rows}
    has_day = modes.get("day", 0) > 0
    # After fix, new entries should be 'day'. Old 'month' entries are historical.
    return ObservationResult(
        name="ouroboros_mode_correct",
        passed=has_day,
        detail=f"modes={modes}",
    )


def observe_stathera_classification(
    client: clickhouse_connect.driver.Client, symbol: str = "BTCUSDT", threshold: int = 250,
) -> ObservationResult:
    """OBSERVATION 4: All gaps = 0, overlaps = 0."""
    cls = stathera_day_classification(client, symbol, threshold)
    return ObservationResult(
        name="stathera_classification",
        passed=(cls.gaps == 0 and cls.overlaps == 0),
        detail=f"gaps={cls.gaps}, overlaps={cls.overlaps}",
    )


def run_all_observations(
    client: clickhouse_connect.driver.Client, symbol: str = "BTCUSDT", threshold: int = 250,
) -> list[ObservationResult]:
    """Run all 4 atomic observations. Returns list of results."""
    results = [
        observe_zero_cross_midnight(client),
        observe_kintsugi_convergence(client),
        observe_ouroboros_mode(client),
        observe_stathera_classification(client, symbol, threshold),
    ]
    for r in results:
        status = "PASS" if r.passed else "FAIL"
        logger.info("[%s] %s: %s", status, r.name, r.detail)
    return results
