"""Per-symbol freshness checks for heartbeat monitoring."""

from __future__ import annotations

import logging
from datetime import datetime, timezone

from heartbeat.config import HEARTBEAT_PRIORITY_SYMBOLS

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


def collect_symbol_freshness(
    client: object,  # clickhouse_connect Client
    results: dict[str, bool | str],
) -> None:
    """Collect per-symbol freshness data.  BTCUSDT shown first."""
    from opendeviationbar.clickhouse.stathera_query import (
        FULL_TABLE as _FT,
    )
    from opendeviationbar.clickhouse.stathera_query import (
        enabled_symbols_sql,
    )

    _sym_filter = enabled_symbols_sql()
    row = client.query(
        f"SELECT symbol, "
        f"  max(toDateTime(intDiv(close_time_us, 1000000), 'UTC')) AS latest_bar, "
        f"  dateDiff('minute', latest_bar, now('UTC')) AS stale_min, "
        f"  count() AS total_bars, "
        f"  min(toDate(intDiv(open_time_us, 1000000), 'UTC')) AS oldest_bar_date "
        f"FROM {_FT} "
        f"WHERE close_time_us > 0 {_sym_filter} "
        f"GROUP BY symbol "
        f"ORDER BY stale_min ASC"
    )
    if not row.result_rows:
        return

    # Load symbol registry for backfill coverage check (best-effort)
    _sym_entries: dict = {}
    try:
        from opendeviationbar.symbol_registry import get_symbol_entries

        _sym_entries = dict(get_symbol_entries())
    except Exception:
        logger.warning("Symbol registry load failed — skipping coverage check", exc_info=True)

    # Build ordered list: priority symbols first, then by freshness
    priority_rows = []
    other_rows = []
    for sym, latest, stale_min, total_bars, oldest_bar_date in row.result_rows:
        entry = (sym, latest, stale_min, total_bars, oldest_bar_date)
        if sym in HEARTBEAT_PRIORITY_SYMBOLS:
            priority_rows.append(entry)
        else:
            other_rows.append(entry)

    ordered = priority_rows + other_rows

    # Store as JSON-like list for the formatter
    freshness_lines = []
    needs_backfill: list[str] = []
    needs_seeding: list[str] = []
    _today = datetime.now(timezone.utc).date()
    _genesis_onboarding_days = 30  # symbol < this many days old = genesis case
    for sym, _latest, stale_min, total_bars, oldest_bar_date in ordered[:8]:  # Top 8
        stale_h = stale_min / 60
        if stale_h < 1:
            age_str = f"{stale_min}m"
        elif stale_h < 24:
            age_str = f"{stale_h:.1f}h"
        else:
            age_str = f"{stale_h / 24:.1f}d"
        is_priority = sym in HEARTBEAT_PRIORITY_SYMBOLS
        prefix = "\U0001f4e1" if is_priority else "    "  # 📡 = live streaming

        backfill_warn = ""
        if _sym_entries:
            entry = _sym_entries.get(sym)
            if entry is not None:
                start = entry.effective_start or entry.listing_date
                days_since = (_today - start).days
                n_thresholds = len(entry.thresholds) if entry.thresholds else 1
                min_expected = days_since * n_thresholds
                if min_expected > 0 and total_bars < min_expected * 0.10:
                    oldest_age_days = (
                        (_today - oldest_bar_date).days
                        if oldest_bar_date is not None
                        else 0
                    )
                    is_genesis = oldest_age_days < _genesis_onboarding_days and days_since > 365
                    if is_genesis:
                        backfill_warn = (
                            f" \u26a0\ufe0f needs initial seeding"
                            f" ({oldest_age_days}d of data, history from {start})"
                        )
                        needs_seeding.append(sym)
                    else:
                        backfill_warn = " \u26a0\ufe0f needs kintsugi:catchup"
                        needs_backfill.append(sym)

        freshness_lines.append(
            f"{prefix} {sym}: {age_str} ago ({total_bars:,} bars){backfill_warn}"
        )

    results["symbol_freshness"] = "\n".join(freshness_lines)
    if needs_backfill:
        results["symbol_needs_backfill"] = ", ".join(needs_backfill)
    if needs_seeding:
        results["symbol_needs_seeding"] = ", ".join(needs_seeding)
