"""Options/derivatives overlay pipeline functions."""

from __future__ import annotations

import logging
from typing import Any, Callable

from horizon._horizon import (
    build_options_chain,
    vol_surface,
    term_structure,
    synthetic_butterfly,
    synthetic_straddle,
    calendar_spread_legs,
)

logger = logging.getLogger("horizon")


def options_chain(
    market_feeds: dict[str, str],
    expiry_days: dict[str, float] | None = None,
    default_expiry: float = 30.0,
) -> Callable:
    """Build a synthetic options chain from prediction market prices."""
    from horizon._horizon import auth_require_ultra
    auth_require_ultra()

    def _fn(ctx) -> dict[str, Any]:
        ids = []
        prices = []
        expiries = []

        for market_id, feed_name in market_feeds.items():
            feed = ctx.feeds.get(feed_name)
            if feed and feed.price > 0:
                ids.append(market_id)
                prices.append(feed.price)
                exp = default_expiry
                if expiry_days and market_id in expiry_days:
                    exp = expiry_days[market_id]
                expiries.append(exp)

        if not ids:
            return {"chain": [], "num_options": 0}

        chain = build_options_chain(ids, prices, expiries)
        chain_data = [
            {
                "market": o.market_id,
                "price": o.price,
                "iv": o.implied_vol,
                "delta": o.delta,
                "gamma": o.gamma,
                "theta": o.theta,
                "vega": o.vega,
            }
            for o in chain
        ]

        return {"chain": chain_data, "num_options": len(chain_data)}

    _fn.__name__ = "options_chain"
    return _fn


def delta_hedge_continuous(
    market_feeds: dict[str, str],
    hedge_threshold: float = 0.1,
    default_expiry: float = 30.0,
) -> Callable:
    """Continuous delta hedging for prediction market positions."""
    from horizon._horizon import auth_require_ultra
    auth_require_ultra()

    last_deltas: dict[str, float] = {}

    def _fn(ctx) -> dict[str, Any]:
        ids = []
        prices = []
        expiries = []

        for mid, fname in market_feeds.items():
            feed = ctx.feeds.get(fname)
            if feed and feed.price > 0:
                ids.append(mid)
                prices.append(feed.price)
                expiries.append(default_expiry)

        if not ids:
            return {"hedge_actions": [], "portfolio_delta": 0.0}

        chain = build_options_chain(ids, prices, expiries)
        hedge_actions = []
        portfolio_delta = 0.0

        for opt in chain:
            old_delta = last_deltas.get(opt.market_id, opt.delta)
            delta_change = abs(opt.delta - old_delta)
            last_deltas[opt.market_id] = opt.delta
            portfolio_delta += opt.delta

            if delta_change > hedge_threshold:
                hedge_actions.append({
                    "market": opt.market_id,
                    "delta_change": delta_change,
                    "new_delta": opt.delta,
                    "hedge_size": delta_change * 100,
                })

        return {
            "hedge_actions": hedge_actions,
            "portfolio_delta": portfolio_delta,
            "num_options": len(chain),
        }

    _fn.__name__ = "delta_hedge_continuous"
    return _fn


def vol_surface_monitor(
    market_feeds: dict[str, str],
    expiry_days: dict[str, float] | None = None,
    default_expiry: float = 30.0,
) -> Callable:
    """Monitor the volatility surface across prediction markets."""
    from horizon._horizon import auth_require_ultra
    auth_require_ultra()

    vol_history: list[float] = []

    def _fn(ctx) -> dict[str, Any]:
        strikes = []
        expiries = []
        prices = []

        for mid, fname in market_feeds.items():
            feed = ctx.feeds.get(fname)
            if feed and feed.price > 0:
                strikes.append(feed.price)
                exp = default_expiry
                if expiry_days and mid in expiry_days:
                    exp = expiry_days[mid]
                expiries.append(exp)
                prices.append(feed.price)

        if not prices:
            return {"surface": [], "avg_iv": 0.0, "iv_change": 0.0}

        surface = vol_surface(strikes, expiries, prices)
        avg_iv = sum(p.implied_vol for p in surface) / max(len(surface), 1)
        vol_history.append(avg_iv)
        if len(vol_history) > 100:
            vol_history.pop(0)

        iv_change = avg_iv - vol_history[-2] if len(vol_history) >= 2 else 0.0

        return {
            "surface": [{"strike": p.strike, "expiry": p.expiry_days, "iv": p.implied_vol} for p in surface],
            "avg_iv": avg_iv,
            "iv_change": iv_change,
        }

    _fn.__name__ = "vol_surface_monitor"
    return _fn
