"""
クライアントCLIエントリーポイント

コマンドラインからレシーバーを起動し、
MBO/Tradeデータの受信と表示を行う。
"""

import argparse
import logging
import signal
import sys
import time

from rich.console import Console
from rich.live import Live
from rich.table import Table
from rich.logging import RichHandler

from ..config import BridgeConfig
from ..models import MBOEvent, TradeEvent, Side
from .receiver import ZmqReceiver
from .order_book import OrderBook
from .trade_analyzer import TradeAnalyzer

console = Console()


def setup_logging(verbose: bool = False) -> None:
    """ロギング設定"""
    level = logging.DEBUG if verbose else logging.INFO
    logging.basicConfig(
        level=level,
        format="%(message)s",
        datefmt="[%X]",
        handlers=[RichHandler(
            console=console,
            rich_tracebacks=True,
        )],
    )


def build_status_table(
    order_book: OrderBook,
    trade_analyzer: TradeAnalyzer,
    receiver: ZmqReceiver,
) -> Table:
    """状態表示用のリッチテーブルを構築する"""
    # メインテーブル
    table = Table(title="Rithmic Bridge クライアント", expand=True)
    table.add_column("項目", style="cyan", width=20)
    table.add_column("値", style="white", width=30)
    table.add_column("項目", style="cyan", width=20)
    table.add_column("値", style="white", width=30)

    # 板情報
    best_bid = order_book.get_best_bid()
    best_ask = order_book.get_best_ask()
    mid = order_book.get_mid_price()
    spread = order_book.get_spread()
    imbalance = order_book.get_book_imbalance()

    # 約定統計
    stats = trade_analyzer.get_stats()
    cum_delta = trade_analyzer.get_cumulative_delta()

    # 受信統計
    rx_stats = receiver.stats

    # 行1: 最良Bid/Ask
    bid_str = f"{best_bid[0]:.1f} x {best_bid[1]}" if best_bid else "-"
    ask_str = f"{best_ask[0]:.1f} x {best_ask[1]}" if best_ask else "-"
    table.add_row("Best Bid", f"[green]{bid_str}[/]", "Best Ask", f"[red]{ask_str}[/]")

    # 行2: Mid Price / Spread
    mid_str = f"{mid:.1f}" if mid else "-"
    spread_str = f"{spread:.1f}" if spread else "-"
    table.add_row("Mid Price", mid_str, "Spread", spread_str)

    # 行3: インバランス / 注文数
    imb_color = "green" if imbalance > 0 else "red" if imbalance < 0 else "white"
    table.add_row(
        "Book Imbalance",
        f"[{imb_color}]{imbalance:+.3f}[/]",
        "Active Orders",
        str(order_book.order_count),
    )

    # 行4: Buy/Sell Volume
    table.add_row(
        "Buy Volume",
        f"[green]{stats.buy_volume}[/]",
        "Sell Volume",
        f"[red]{stats.sell_volume}[/]",
    )

    # 行5: OFI / Cumulative Delta
    ofi_color = "green" if stats.ofi > 0 else "red" if stats.ofi < 0 else "white"
    delta_color = "green" if cum_delta > 0 else "red" if cum_delta < 0 else "white"
    table.add_row(
        "OFI",
        f"[{ofi_color}]{stats.ofi:+.3f}[/]",
        "Cum Delta",
        f"[{delta_color}]{cum_delta:+d}[/]",
    )

    # 行6: VWAP / Last Price
    table.add_row(
        "VWAP",
        f"{stats.vwap:.1f}" if stats.vwap > 0 else "-",
        "Last Price",
        f"{stats.last_price:.1f}" if stats.last_price > 0 else "-",
    )

    # 行7: 受信統計
    total_rx = rx_stats.get("mbo_count", 0) + rx_stats.get("trade_count", 0)
    table.add_row(
        "MBO受信数",
        str(rx_stats.get("mbo_count", 0)),
        "Trade受信数",
        str(rx_stats.get("trade_count", 0)),
    )

    # 行8: 板レベル数
    table.add_row(
        "Bidレベル数",
        str(order_book.bid_level_count),
        "Askレベル数",
        str(order_book.ask_level_count),
    )

    # 行9: レイテンシ / 接続状態
    latency = rx_stats.get("latency_ms", 0.0)
    lat_color = "green" if 0 < latency < 5 else "yellow" if latency < 20 else "red"
    connected = rx_stats.get("publisher_connected", False)
    conn_str = "[green]● 接続中[/]" if connected else "[red]● 切断[/]"
    table.add_row(
        "レイテンシ",
        f"[{lat_color}]{latency:.2f}ms[/]" if latency > 0 else "[dim]-[/]",
        "パブリッシャー",
        conn_str,
    )

    # 行10: Heartbeat / 欠落
    hb_count = rx_stats.get("heartbeat_count", 0)
    missed = rx_stats.get("missed_heartbeats", 0)
    missed_color = "green" if missed == 0 else "red"
    table.add_row(
        "Heartbeat受信",
        str(hb_count),
        "HB欠落",
        f"[{missed_color}]{missed}[/]",
    )

    return table


def main() -> None:
    """クライアントメインエントリーポイント"""
    parser = argparse.ArgumentParser(
        description="Rithmic Bridge クライアント - MBO & 約定データ受信",
    )
    parser.add_argument(
        "--host",
        type=str,
        default=None,
        help="接続先ホスト (デフォルト: .env のCLIENT_HOST)",
    )
    parser.add_argument(
        "--port",
        type=int,
        default=None,
        help="接続先ポート (デフォルト: .env のCLIENT_PORT)",
    )
    parser.add_argument(
        "--env-file",
        type=str,
        default=None,
        help=".envファイルのパス",
    )
    parser.add_argument(
        "--symbol",
        type=str,
        default=None,
        help="購読するシンボル (例: GCJ6)",
    )
    parser.add_argument(
        "--exchange",
        type=str,
        default=None,
        help="取引所 (例: COMEX)",
    )
    parser.add_argument(
        "--req-port",
        type=int,
        default=None,
        help="ZeroMQ REQ (コマンド) ポート (デフォルト: .env のCLIENT_REQ_PORT)",
    )
    parser.add_argument(
        "--raw",
        action="store_true",
        help="生のイベントデータをそのまま表示する",
    )
    parser.add_argument(
        "-v", "--verbose",
        action="store_true",
        help="詳細ログを表示",
    )

    args = parser.parse_args()

    # ロギング設定
    setup_logging(verbose=args.verbose)
    logger = logging.getLogger(__name__)

    # 設定読み込み
    config = BridgeConfig.from_env(env_file=args.env_file)

    # コマンドライン引数で上書き
    if args.host:
        config.zmq.client_host = args.host
    if args.port:
        config.zmq.client_port = args.port
    if args.req_port:
        config.zmq.req_port = args.req_port
    
    # シンボル情報の決定
    symbol = args.symbol or config.rithmic.symbol
    exchange = args.exchange or config.rithmic.exchange
    full_symbol = f"{symbol}.{exchange}"

    # ヘッダー表示
    console.print("")
    console.print("[bold blue]═══════════════════════════════════════[/]")
    console.print("[bold blue]  Rithmic Bridge クライアント[/]")
    console.print("[bold blue]═══════════════════════════════════════[/]")
    console.print(f"  接続先: [bold]{config.get_sub_connect_addr()}[/]")
    console.print(f"  対象銘柄: [bold]{full_symbol}[/]")
    console.print("[bold blue]═══════════════════════════════════════[/]")
    console.print("")

    # コンポーネント初期化
    # RithmicClientを使用するように変更
    from .library import RithmicClient
    
    # 既存の config オブジェクトから設定を引き継ぐ形で初期化
    client = RithmicClient(
        host=config.zmq.client_host,
        port=config.zmq.client_port,
        req_port=config.zmq.req_port
    )
    
    order_book = OrderBook(symbol=full_symbol)
    trade_analyzer = TradeAnalyzer(window_size=100)
    # receiver = ZmqReceiver(config) # 削除

    # コールバック登録
    if args.raw:
        # 生データ表示モード
        def on_mbo(event: MBOEvent) -> None:
            console.print(f"[cyan]MBO[/] {event.to_json()}")

        def on_trade(event: TradeEvent) -> None:
            color = "green" if event.aggressor_side == Side.BID else "red"
            console.print(f"[{color}]TRADE[/] {event.to_json()}")
    else:
        # 構造化表示モード
        def on_mbo(event: MBOEvent) -> None:
            order_book.process_event(event)

        def on_trade(event: TradeEvent) -> None:
            trade_analyzer.process_event(event)

    client.on_mbo(on_mbo)
    client.on_trade(on_trade)

    # クライアント接続開始
    client.connect()
    
    # 動的購読 (引数が指定されている場合、または設定ファイルの値を使用)
    # サーバー側で自動購読が無効化されたため、明示的に購読リクエストを送る必要がある
    if symbol and exchange:
        console.print(f"[yellow]購読リクエスト送信中: {full_symbol}...[/]")
        # 少し待機してから送信
        time.sleep(0.5)
        if client.subscribe(symbol, exchange):
            console.print(f"[green]購読成功: {full_symbol}[/]")
        else:
            console.print(f"[red]購読失敗: {full_symbol}[/]")

    # シグナルハンドラー設定
    shutdown_event = False

    def signal_handler(signum, frame):
        nonlocal shutdown_event
        if not shutdown_event:
            shutdown_event = True

    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    # メインループ
    console.print("[green]クライアント稼働中 (Ctrl+C で停止)[/]\n")

    if args.raw:
        # 生データモード - イベントをそのまま表示
        try:
            while not shutdown_event:
                time.sleep(0.1)
        except KeyboardInterrupt:
            pass
    else:
        # 構造化表示モード - リアルタイムダッシュボード
        # receiver.stats へのアクセスを client.receiver.stats に変更する必要がある
        try:
            with Live(
                build_status_table(order_book, trade_analyzer, client.receiver),
                refresh_per_second=4,
                console=console,
            ) as live:
                while not shutdown_event:
                    time.sleep(0.25)
                    live.update(
                        build_status_table(order_book, trade_analyzer, client.receiver)
                    )
        except KeyboardInterrupt:
            pass

    # クリーンアップ
    console.print("\n[yellow]クリーンアップ中...[/]")
    client.disconnect()
    console.print("[bold green]✓ クライアント正常終了[/]")


if __name__ == "__main__":
    main()
