"""Treasury yield curve pipeline functions."""

from __future__ import annotations

import logging
from dataclasses import dataclass
from typing import Any, Callable

from horizon._horizon import (
    yield_adjusted_kelly,
    yield_adjusted_kelly_size,
    opportunity_cost,
    breakeven_edge,
)

logger = logging.getLogger("horizon")


def yield_adjusted_sizer(
    rfr_feed: str = "treasury",
    duration_days: float = 30.0,
    fraction: float = 0.5,
    bankroll: float = 10000.0,
    max_size: float = 1000.0,
) -> Callable:
    """Size positions using yield-adjusted Kelly criterion.

    Reduces position size when the risk-free rate makes the opportunity
    cost of capital too high relative to the edge.
    """
    from horizon._horizon import auth_require_ultra
    auth_require_ultra()

    def _fn(ctx) -> dict[str, Any]:
        feed = ctx.feeds.get(rfr_feed)
        rfr = feed.price if feed and feed.price > 0 else 0.0
        prob = ctx.params.get("prob", 0.5)
        price = ctx.feed.price if ctx.feed else 0.5

        size = yield_adjusted_kelly_size(
            prob, price, rfr, duration_days, bankroll, fraction, max_size
        )
        be = breakeven_edge(rfr, duration_days)
        oc = opportunity_cost(bankroll * price, rfr, duration_days)
        ya_kelly = yield_adjusted_kelly(prob, price, rfr, duration_days, fraction)

        return {
            "size": size,
            "yield_adjusted_kelly": ya_kelly,
            "breakeven_edge": be,
            "opportunity_cost": oc,
            "rfr": rfr,
        }

    _fn.__name__ = "yield_adjusted_sizer"
    return _fn


def opportunity_cost_filter(
    rfr_feed: str = "treasury",
    duration_days: float = 30.0,
    min_edge_multiple: float = 2.0,
) -> Callable:
    """Filter out trades where edge doesn't justify opportunity cost."""
    from horizon._horizon import auth_require_ultra
    auth_require_ultra()

    def _fn(ctx) -> dict[str, Any]:
        feed = ctx.feeds.get(rfr_feed)
        rfr = feed.price if feed and feed.price > 0 else 0.0
        prob = ctx.params.get("prob", 0.5)
        price = ctx.feed.price if ctx.feed else 0.5

        be = breakeven_edge(rfr, duration_days)
        raw_edge = prob - price
        should_trade = abs(raw_edge) > be * min_edge_multiple

        return {
            "should_trade": should_trade,
            "raw_edge": raw_edge,
            "breakeven_edge": be,
            "edge_ratio": abs(raw_edge) / max(be, 1e-10),
        }

    _fn.__name__ = "opportunity_cost_filter"
    return _fn


def collateral_optimizer(
    rfr_feed: str = "treasury",
    max_utilization: float = 0.8,
) -> Callable:
    """Optimize capital allocation considering yield curve shape."""
    from horizon._horizon import auth_require_ultra
    auth_require_ultra()

    def _fn(ctx) -> dict[str, Any]:
        feed = ctx.feeds.get(rfr_feed)
        if not feed:
            return {"optimal_allocation": max_utilization, "curve_signal": 0.0}

        short_rate = feed.bid  # short-term yield
        long_rate = feed.ask  # long-term yield
        slope = feed.volume_24h  # slope in bps

        # Steeper curve = more opportunity cost, reduce allocation
        curve_penalty = max(0, slope / 200.0)  # 200bps = full penalty
        optimal = max(0.1, max_utilization - curve_penalty)

        return {
            "optimal_allocation": optimal,
            "curve_signal": slope,
            "short_rate": short_rate,
            "long_rate": long_rate,
        }

    _fn.__name__ = "collateral_optimizer"
    return _fn
