"""Upload EURUSD open deviation bars to ClickHouse cache.

# Issue #144: Generate EURUSD open deviation bars and cache in ClickHouse

Reads generated parquet files and uploads to bigblack ClickHouse.
Uses Polars for all data processing (no pandas).

Usage:
    OPENDEVIATIONBAR_CH_HOSTS=bigblack uv run python scripts/upload_eurusd_to_clickhouse.py
"""

import json
from datetime import UTC, datetime
from pathlib import Path

import polars as pl


def log(level: str, message: str, **kwargs: object) -> None:
    """Log in NDJSON format."""
    entry = {
        "timestamp": datetime.now(UTC).isoformat(),
        "level": level,
        "message": message,
        **kwargs,
    }
    print(json.dumps(entry), flush=True)


def upload_to_clickhouse(
    parquet_path: Path,
    symbol: str,
    threshold_decimal_bps: int,
) -> int:
    """Upload open deviation bars to ClickHouse using Polars with SSH tunnel.

    Returns number of rows inserted.
    """
    import clickhouse_connect
    from opendeviationbar.clickhouse.tunnel import SSHTunnel

    # Read parquet with Polars
    bars_df = pl.read_parquet(parquet_path)

    # The parquet has Open, High, Low, Close, Volume columns
    # Transform to ClickHouse schema
    insert_df = bars_df.with_columns(
        [
            pl.lit(symbol).alias("symbol"),
            pl.lit(threshold_decimal_bps)
            .cast(pl.UInt32)
            .alias("threshold_decimal_bps"),
            # Timestamp column (datetime to epoch ms)
            (pl.col("timestamp").dt.epoch("ms")).alias("close_time_us"),
            pl.col("Open").alias("open"),
            pl.col("High").alias("high"),
            pl.col("Low").alias("low"),
            pl.col("Close").alias("close"),
            pl.col("Volume").alias("volume"),
            # Defaults for forex (no microstructure)
            pl.lit(0.0).alias("vwap"),
            pl.lit(0.0).alias("buy_volume"),
            pl.lit(0.0).alias("sell_volume"),
            pl.lit(0).cast(pl.UInt32).alias("individual_trade_count"),
            pl.lit(0).cast(pl.UInt32).alias("agg_record_count"),
            pl.lit(f"{symbol}_{threshold_decimal_bps}_forex").alias("cache_key"),
            pl.lit("11.4.0").alias("opendeviationbar_version"),
            pl.lit(0).cast(pl.Int64).alias("source_start_ts"),
            pl.lit(0).cast(pl.Int64).alias("source_end_ts"),
            pl.lit("none").alias("ouroboros_mode"),
        ]
    ).select(
        [
            "symbol",
            "threshold_decimal_bps",
            "close_time_us",
            "open",
            "high",
            "low",
            "close",
            "volume",
            "vwap",
            "buy_volume",
            "sell_volume",
            "individual_trade_count",
            "agg_record_count",
            "cache_key",
            "opendeviationbar_version",
            "source_start_ts",
            "source_end_ts",
            "ouroboros_mode",
        ]
    )

    # Connect via SSH tunnel to bigblack
    with SSHTunnel("bigblack") as local_port:
        client = clickhouse_connect.get_client(
            host="localhost",
            port=local_port,
            username="default",
            password="",
        )

        # Insert using arrow format (zero-copy from Polars)
        client.insert_arrow(
            "opendeviationbar_cache.open_deviation_bars",
            insert_df.to_arrow(),
        )

    return len(insert_df)


def main() -> None:
    """Upload EURUSD open deviation bars to ClickHouse."""
    cache_dir = Path.home() / "Library/Caches/opendeviationbar/forex/EURUSD_Raw_Spread"

    log("INFO", "Starting ClickHouse upload")

    thresholds = [50, 100, 200]
    total_rows = 0

    for threshold in thresholds:
        parquet_path = cache_dir / f"open_deviation_bars_{threshold}dbps.parquet"
        if not parquet_path.exists():
            log(
                "WARN",
                "Parquet file not found",
                threshold_dbps=threshold,
                path=str(parquet_path),
            )
            continue

        log("INFO", "Uploading bars", threshold_dbps=threshold)

        rows = upload_to_clickhouse(parquet_path, "EURUSD", threshold)
        total_rows += rows
        log("INFO", "Uploaded", threshold_dbps=threshold, rows=rows)

    log("INFO", "Upload complete", total_rows=total_rows)


if __name__ == "__main__":
    main()
