"""Latency arbitrage: fast reference feed detects moves before book updates.

Uses a fast external feed (e.g., BinanceWS) to detect price moves before
the prediction market book reprices. Front-runs the expected repricing.

Ultra tier only.
"""

from __future__ import annotations

import logging
import time
from typing import Callable

from horizon.context import Context

logger = logging.getLogger(__name__)


def latency_arb(
    market_id: str,
    ref_feed: str,
    market_feed: str,
    sensitivity: float = 1.0,
    min_staleness_ms: float = 500.0,
    min_edge: float = 0.02,
    max_size: float = 20.0,
    fee_rate: float = 0.002,
    auto_execute: bool = False,
    cooldown: float = 2.0,
    max_daily_trades: int = 50,
) -> Callable[[Context], None]:
    """Create a pipeline function for latency arbitrage.

    Monitors a fast reference feed and the prediction market book.
    When the reference feed shows a significant move and the market
    book is stale, generates a trade signal.

    Args:
        market_id: Market to trade.
        ref_feed: Fast reference feed name (e.g., Binance).
        market_feed: Prediction market feed name.
        sensitivity: Multiplier for reference price moves (1.0 = 1:1).
        min_staleness_ms: Minimum book staleness in milliseconds.
        min_edge: Minimum edge after fees.
        max_size: Maximum trade size.
        fee_rate: Fee rate per trade.
        auto_execute: If True, execute trades automatically.
        cooldown: Seconds between executions.
        max_daily_trades: Hard cap on daily trades (safety).

    Returns:
        Pipeline function: (Context) -> None
    """
    from horizon._horizon import auth_require_ultra
    auth_require_ultra()

    last_exec_time = 0.0
    daily_trades = 0
    last_reset_day = 0

    def _scanner(ctx: Context) -> None:
        nonlocal last_exec_time, daily_trades, last_reset_day

        engine = ctx.params.get("engine")
        if engine is None:
            return None

        # Daily trade counter reset
        today = int(time.time() / 86400)
        if today != last_reset_day:
            daily_trades = 0
            last_reset_day = today

        if daily_trades >= max_daily_trades:
            return None

        opp = engine.scan_latency_arb(
            market_id, ref_feed, market_feed,
            sensitivity, min_staleness_ms, min_edge, fee_rate,
        )
        if opp is None:
            return None

        ctx.params["last_latency_arb"] = opp

        if auto_execute:
            now = time.monotonic()
            if now - last_exec_time >= cooldown:
                try:
                    from horizon._horizon import OrderSide, Side

                    if opp.direction == "buy":
                        engine.submit_order(
                            market_id, Side.Yes, OrderSide.Buy,
                            max_size, opp.market_price,
                        )
                    else:
                        engine.submit_order(
                            market_id, Side.Yes, OrderSide.Sell,
                            max_size, opp.market_price,
                        )

                    last_exec_time = now
                    daily_trades += 1
                    logger.info(
                        "Latency arb executed: %s dir=%s edge=%.4f stale=%.0fms trades=%d/%d",
                        market_id, opp.direction, opp.edge,
                        opp.staleness_ms, daily_trades, max_daily_trades,
                    )
                except Exception as e:
                    logger.warning("Latency arb execution failed for %s: %s", market_id, e)

        return None

    _scanner.__name__ = "latency_arb"
    return _scanner
