#!/usr/bin/env python3
# Issue #187: Identify and delete bars below min_threshold per symbols.toml.
"""Cleanup illegitimate bars: bars at thresholds below the symbol's min_threshold.

These bars were created before the symbol registry gate was enforced.
They waste storage, slow queries, and cause kintsugi to discover false gaps.

Dry-run by default. Use --apply to execute deletions.

Usage:
    python scripts/cleanup_illegitimate_bars.py              # Audit (dry run)
    python scripts/cleanup_illegitimate_bars.py --apply      # Execute deletions
    python scripts/cleanup_illegitimate_bars.py --json       # Machine-readable output
"""

from __future__ import annotations

import argparse
import json
import logging
import sys

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s | %(levelname)-8s | %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)
logger = logging.getLogger("cleanup-illegitimate-bars")


def main() -> int:
    parser = argparse.ArgumentParser(
        description="Audit and clean up bars below symbol min_threshold.",
    )
    parser.add_argument(
        "--apply",
        action="store_true",
        help="Execute deletions (default is dry-run audit).",
    )
    parser.add_argument(
        "--json",
        action="store_true",
        help="Output results as JSON.",
    )
    args = parser.parse_args()

    try:
        import clickhouse_connect
        from opendeviationbar.symbol_registry import get_symbol_entries
    except ImportError:
        logger.warning("Required packages not installed (clickhouse_connect, opendeviationbar)")
        return 2

    client = clickhouse_connect.get_client(host="localhost", port=8123)
    registry = get_symbol_entries()

    # Step 1: Get all (symbol, threshold) pairs in ClickHouse with bar counts
    rows = client.query(
        "SELECT symbol, threshold_decimal_bps, count() AS bar_count "
        "FROM opendeviationbar_cache.open_deviation_bars "
        "GROUP BY symbol, threshold_decimal_bps "
        "ORDER BY symbol, threshold_decimal_bps"
    )

    illegitimate: list[dict] = []
    total_bars_to_delete = 0

    for symbol, threshold, bar_count in rows.result_rows:
        info = registry.get(symbol)
        if info is None:
            continue  # Symbol not in registry — separate concern

        # Only flag if symbols.toml defines a per-symbol min_threshold
        min_threshold = info.min_threshold
        if min_threshold is not None and threshold < min_threshold:
            entry = {
                "symbol": symbol,
                "threshold": threshold,
                "min_threshold": min_threshold,
                "bar_count": bar_count,
            }
            illegitimate.append(entry)
            total_bars_to_delete += bar_count

    if args.json:
        print(json.dumps({
            "illegitimate_pairs": illegitimate,
            "total_bars": total_bars_to_delete,
            "apply": args.apply,
        }, indent=2))
    else:
        if not illegitimate:
            logger.info("No illegitimate bars found. All pairs comply with symbols.toml.")
            return 0

        logger.info(
            "Found %d illegitimate (symbol, threshold) pairs with %s total bars:",
            len(illegitimate),
            f"{total_bars_to_delete:,}",
        )
        for entry in illegitimate:
            logger.info(
                "  %s @ %d dbps: %s bars (min_threshold=%d)",
                entry["symbol"],
                entry["threshold"],
                f"{entry['bar_count']:,}",
                entry["min_threshold"],
            )

    if not args.apply:
        if not args.json:
            logger.info("Dry run complete. Use --apply to delete these bars.")
        return 1 if illegitimate else 0

    # Step 2: Delete illegitimate bars
    total_deleted = 0
    for entry in illegitimate:
        logger.info(
            "Deleting %s @ %d dbps (%s bars)...",
            entry["symbol"],
            entry["threshold"],
            f"{entry['bar_count']:,}",
        )
        client.command(
            "ALTER TABLE opendeviationbar_cache.open_deviation_bars "
            "DELETE WHERE symbol = %(symbol)s AND threshold_decimal_bps = %(threshold)s",
            parameters={
                "symbol": entry["symbol"],
                "threshold": entry["threshold"],
            },
        )
        total_deleted += entry["bar_count"]

    logger.info("Deleted %s illegitimate bars across %d pairs.", f"{total_deleted:,}", len(illegitimate))

    # Step 3: Notify via Telegram
    try:
        from opendeviationbar.notify.telegram import send_telegram

        pairs_str = ", ".join(f"{e['symbol']}@{e['threshold']}" for e in illegitimate[:5])
        if len(illegitimate) > 5:
            pairs_str += f" (+{len(illegitimate) - 5} more)"
        send_telegram(
            f"\U0001f9f9 <b>Illegitimate bar cleanup</b>: deleted {total_deleted:,} bars "
            f"below min_threshold across {len(illegitimate)} pairs: {pairs_str}",
            disable_notification=False,
        )
    except (ImportError, OSError, RuntimeError):
        logger.debug("Telegram notification skipped", exc_info=True)

    return 0


if __name__ == "__main__":
    sys.exit(main())
