"""Cross-venue liquidity aggregation pipeline functions."""

from __future__ import annotations

import logging
from typing import Any, Callable

from horizon._horizon import (
    aggregate_books,
    smart_route,
    best_venue,
    merged_mid_price,
    AggregatedBook,
)

logger = logging.getLogger("horizon")


def aggregate_book(
    venue_feeds: dict[str, dict[str, str]],
) -> Callable:
    """Aggregate orderbooks from multiple venues.

    venue_feeds: {venue_name: {"bid_feed": feed_name, "ask_feed": feed_name}}
    """
    from horizon._horizon import auth_require_ultra
    auth_require_ultra()

    def _fn(ctx) -> dict[str, Any]:
        bids = []
        asks = []

        for venue, feeds_cfg in venue_feeds.items():
            bid_feed = ctx.feeds.get(feeds_cfg.get("bid_feed", ""))
            ask_feed = ctx.feeds.get(feeds_cfg.get("ask_feed", feeds_cfg.get("bid_feed", "")))

            if bid_feed and bid_feed.bid > 0:
                size = bid_feed.volume_24h if bid_feed.volume_24h > 0 else 100.0
                bids.append((venue, bid_feed.bid, size))
            if ask_feed and ask_feed.ask > 0:
                size = ask_feed.volume_24h if ask_feed.volume_24h > 0 else 100.0
                asks.append((venue, ask_feed.ask, size))

        book = aggregate_books(bids, asks)

        return {
            "best_bid": book.best_bid,
            "best_ask": book.best_ask,
            "mid_price": book.mid_price,
            "spread": book.best_ask - book.best_bid if book.best_ask > 0 and book.best_bid > 0 else 0.0,
            "bid_depth": book.total_bid_size,
            "ask_depth": book.total_ask_size,
            "num_bid_levels": len(book.bids),
            "num_ask_levels": len(book.asks),
        }

    _fn.__name__ = "aggregate_book"
    return _fn


def smart_route_pipeline(
    venue_feeds: dict[str, dict[str, str]],
    default_size: float = 100.0,
) -> Callable:
    """Smart order routing across venues."""
    from horizon._horizon import auth_require_ultra
    auth_require_ultra()

    def _fn(ctx) -> dict[str, Any]:
        bids = []
        asks = []

        for venue, feeds_cfg in venue_feeds.items():
            feed = ctx.feeds.get(feeds_cfg.get("bid_feed", ""))
            if not feed:
                continue
            if feed.bid > 0:
                bids.append((venue, feed.bid, feed.volume_24h or 100.0))
            if feed.ask > 0:
                asks.append((venue, feed.ask, feed.volume_24h or 100.0))

        book = aggregate_books(bids, asks)
        size = ctx.params.get("size", default_size)
        side = ctx.params.get("side", "buy")

        decision = smart_route(book, side, size)

        return {
            "venue": decision.venue,
            "price": decision.price,
            "size": decision.size,
            "expected_cost": decision.expected_cost,
            "fills": [{"venue": v, "price": p, "size": s} for v, p, s in decision.fills_across_venues],
        }

    _fn.__name__ = "smart_route"
    return _fn


def cross_venue_mm(
    venue_feeds: dict[str, dict[str, str]],
    spread_markup: float = 0.01,
    size: float = 50.0,
) -> Callable:
    """Cross-venue market making using aggregated book."""
    from horizon._horizon import auth_require_ultra
    auth_require_ultra()

    def _fn(ctx) -> dict[str, Any]:
        bids = []
        asks = []

        for venue, feeds_cfg in venue_feeds.items():
            feed = ctx.feeds.get(feeds_cfg.get("bid_feed", ""))
            if not feed:
                continue
            if feed.bid > 0:
                bids.append((venue, feed.bid, feed.volume_24h or 100.0))
            if feed.ask > 0:
                asks.append((venue, feed.ask, feed.volume_24h or 100.0))

        book = aggregate_books(bids, asks)

        if book.best_bid <= 0 or book.best_ask <= 0:
            return {"quotes": [], "mid": 0.0}

        mid = book.mid_price
        half_spread = spread_markup / 2
        our_bid = max(0.01, mid - half_spread)
        our_ask = min(0.99, mid + half_spread)

        # Find best venue for each side
        bid_venue, _ = best_venue(book, "sell")
        ask_venue, _ = best_venue(book, "buy")

        quotes = []
        if our_bid < our_ask:
            quotes.append({"side": "bid", "price": our_bid, "size": size, "venue": bid_venue})
            quotes.append({"side": "ask", "price": our_ask, "size": size, "venue": ask_venue})

        return {
            "quotes": quotes,
            "mid": mid,
            "spread": our_ask - our_bid,
            "aggregated_spread": book.best_ask - book.best_bid,
        }

    _fn.__name__ = "cross_venue_mm"
    return _fn
