"""CLI commands for the Market Data Hub."""

from __future__ import annotations

import asyncio
import shutil
import subprocess
import sys
from pathlib import Path

import click

from coinjure.cli.utils import _emit
from coinjure.hub.hub import HUB_PID_PATH, HUB_SOCKET_PATH, send_hub_command

_DEFAULT_HUB_SOCKET = str(HUB_SOCKET_PATH)


@click.group()
def hub() -> None:
    """Shared Market Data Hub — exchange data fan-out server."""
    pass


@hub.command('start')
@click.option(
    '--socket-path', default=_DEFAULT_HUB_SOCKET, show_default=True, type=click.Path()
)
@click.option(
    '--poly-interval',
    default=60.0,
    show_default=True,
    type=float,
    help='Polymarket polling interval in seconds.',
)
@click.option(
    '--kalshi-interval',
    default=60.0,
    show_default=True,
    type=float,
    help='Kalshi polling interval in seconds.',
)
@click.option('--kalshi-api-key-id', default=None, envvar='KALSHI_API_KEY_ID')
@click.option(
    '--kalshi-private-key-path', default=None, envvar='KALSHI_PRIVATE_KEY_PATH'
)
@click.option(
    '--detach/--no-detach',
    default=False,
    help='Run as a detached background process (default: foreground).',
)
@click.option('--json', 'as_json', is_flag=True, default=False)
def hub_start(
    socket_path: str,
    poly_interval: float,
    kalshi_interval: float,
    kalshi_api_key_id: str | None,
    kalshi_private_key_path: str | None,
    detach: bool,
    as_json: bool,
) -> None:
    """Start the shared Market Data Hub (exchange poller)."""
    socket = Path(socket_path).expanduser()

    if detach:
        coinjure_bin = shutil.which('coinjure')
        if coinjure_bin:
            cmd = [coinjure_bin, 'hub', 'start']
        else:
            cmd = [sys.executable, '-m', 'coinjure.cli.cli', 'hub', 'start']

        cmd += [
            '--socket-path',
            str(socket),
            '--poly-interval',
            str(poly_interval),
            '--kalshi-interval',
            str(kalshi_interval),
            '--no-detach',
        ]
        if kalshi_api_key_id:
            cmd += ['--kalshi-api-key-id', kalshi_api_key_id]
        if kalshi_private_key_path:
            cmd += ['--kalshi-private-key-path', kalshi_private_key_path]

        proc = subprocess.Popen(
            cmd,
            start_new_session=True,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
        )
        HUB_PID_PATH.parent.mkdir(parents=True, exist_ok=True)
        HUB_PID_PATH.write_text(str(proc.pid))

        _emit({'ok': True, 'pid': proc.pid, 'socket': str(socket)}, as_json=as_json)
        return

    from coinjure.data.live.kalshi import LiveKalshiDataSource
    from coinjure.data.live.polymarket import LivePolyMarketDataSource
    from coinjure.data.source import CompositeDataSource
    from coinjure.hub.hub import MarketDataHub

    poly = LivePolyMarketDataSource(
        event_cache_file='events_cache.jsonl',
        polling_interval=poly_interval,
        orderbook_refresh_interval=5.0,
        reprocess_on_start=False,
    )
    kalshi = LiveKalshiDataSource(
        api_key_id=kalshi_api_key_id,
        private_key_path=kalshi_private_key_path,
        event_cache_file='kalshi_events_cache.jsonl',
        polling_interval=kalshi_interval,
        reprocess_on_start=False,
    )
    source = CompositeDataSource([poly, kalshi])
    hub_obj = MarketDataHub(socket_path=socket, source=source)

    if not as_json:
        click.echo(f'Starting Market Data Hub on {socket}  (Ctrl-C to stop)')
    try:
        asyncio.run(hub_obj.start())
    except KeyboardInterrupt:
        if not as_json:
            click.echo('\nHub stopped.')


@hub.command('status')
@click.option(
    '--socket-path', default=_DEFAULT_HUB_SOCKET, show_default=True, type=click.Path()
)
@click.option('--json', 'as_json', is_flag=True, default=False)
def hub_status(socket_path: str, as_json: bool) -> None:
    """Show hub status: subscriber count, uptime, events forwarded."""
    socket = Path(socket_path).expanduser()
    if not socket.exists():
        _emit(
            {'ok': False, 'error': f'Hub not running (socket not found: {socket})'},
            as_json=as_json,
        )
        return
    _emit(send_hub_command(socket, 'status'), as_json=as_json)


@hub.command('stop')
@click.option(
    '--socket-path', default=_DEFAULT_HUB_SOCKET, show_default=True, type=click.Path()
)
@click.option('--json', 'as_json', is_flag=True, default=False)
def hub_stop(socket_path: str, as_json: bool) -> None:
    """Stop the running Market Data Hub."""
    socket = Path(socket_path).expanduser()
    if not socket.exists():
        _emit(
            {'ok': False, 'error': f'Hub not running (socket not found: {socket})'},
            as_json=as_json,
        )
        return
    _emit(send_hub_command(socket, 'stop'), as_json=as_json)
