"""Bit-exact ClickHouse oracle queries for day-mode verification."""

from __future__ import annotations

from typing import TYPE_CHECKING, NamedTuple

if TYPE_CHECKING:
    import clickhouse_connect.driver

from opendeviationbar.clickhouse.stathera_query import FULL_TABLE

# Atomic query: count bars spanning UTC midnight
CROSS_MIDNIGHT_QUERY = f"""
    SELECT count() AS violations
    FROM {FULL_TABLE} FINAL
    WHERE symbol = {{symbol:String}}
      AND threshold_decimal_bps = {{threshold:UInt32}}
      AND ouroboros_mode = {{ouroboros:String}}
      AND toDate(open_time_ms / 1000, 'UTC') != toDate(close_time_ms / 1000, 'UTC')
"""

# Scoped variant: check only within a trade-ID range (for verify_repair)
CROSS_MIDNIGHT_RANGE_QUERY = f"""
    SELECT count() AS violations
    FROM {FULL_TABLE} FINAL
    WHERE symbol = {{symbol:String}}
      AND threshold_decimal_bps = {{threshold:UInt32}}
      AND ouroboros_mode = {{ouroboros:String}}
      AND first_agg_trade_id >= {{anchor_tid:Int64}}
      AND first_agg_trade_id <= {{resume_tid:Int64}}
      AND toDate(open_time_ms / 1000, 'UTC') != toDate(close_time_ms / 1000, 'UTC')
"""

# Global query: count all cross-midnight bars (no filters)
GLOBAL_CROSS_MIDNIGHT_QUERY = f"""
    SELECT count() AS violations
    FROM {FULL_TABLE} FINAL
    WHERE toDate(open_time_ms / 1000, 'UTC') != toDate(close_time_ms / 1000, 'UTC')
"""


class StatheraDayClassification(NamedTuple):
    gaps: int
    overlaps: int


def cross_midnight_count(
    client: clickhouse_connect.driver.Client, symbol: str, threshold: int, ouroboros: str = "day",
) -> int:
    """Count cross-midnight bars for a specific (symbol, threshold) pair."""
    result = client.query(
        CROSS_MIDNIGHT_QUERY,
        parameters={"symbol": symbol, "threshold": threshold, "ouroboros": ouroboros},
    )
    return result.first_row[0]


def cross_midnight_count_global(client: clickhouse_connect.driver.Client) -> int:
    """Count ALL cross-midnight bars across entire table."""
    result = client.query(GLOBAL_CROSS_MIDNIGHT_QUERY)
    return result.first_row[0]


def cross_midnight_count_range(
    client: clickhouse_connect.driver.Client,
    symbol: str,
    threshold: int,
    ouroboros: str,
    anchor_tid: int,
    resume_tid: int,
) -> int:
    """Count cross-midnight bars within a trade-ID range (post-repair oracle)."""
    result = client.query(
        CROSS_MIDNIGHT_RANGE_QUERY,
        parameters={
            "symbol": symbol,
            "threshold": threshold,
            "ouroboros": ouroboros,
            "anchor_tid": anchor_tid,
            "resume_tid": resume_tid,
        },
    )
    return result.first_row[0]


def stathera_day_classification(
    client: clickhouse_connect.driver.Client,
    symbol: str,
    threshold: int,
    ouroboros: str = "day",
) -> StatheraDayClassification:
    """Classify Stathera anomalies into gaps and overlaps.

    All tid_delta > 0 are real gaps (REST and Vision produce identical
    deterministic day boundaries, so there are no "structural" gaps).
    """
    query = f"""
        WITH inner AS (
            SELECT first_agg_trade_id,
                   first_agg_trade_id - lagInFrame(last_agg_trade_id, 1) OVER w - 1 AS tid_delta,
                   row_number() OVER w AS rn
            FROM {FULL_TABLE}
            WHERE symbol = {{symbol:String}}
              AND threshold_decimal_bps = {{threshold:UInt32}}
              AND ouroboros_mode = {{ouroboros:String}}
              AND first_agg_trade_id > 0 AND last_agg_trade_id > 0
            WINDOW w AS (ORDER BY first_agg_trade_id, close_time_ms)
        )
        SELECT
            countIf(tid_delta > 0) AS gaps,
            countIf(tid_delta < 0) AS overlaps
        FROM inner WHERE rn > 1
    """
    result = client.query(
        query,
        parameters={"symbol": symbol, "threshold": threshold, "ouroboros": ouroboros},
    )
    row = result.first_row
    return StatheraDayClassification(gaps=row[0], overlaps=row[1])
