"""Shared tool functions for MCP server and OpenClaw skill.

Thin wrappers around the Horizon Engine API that return plain dicts/lists
suitable for JSON serialization. Both the MCP server and the OpenClaw CLI
delegate to these functions.
"""

from __future__ import annotations

import math
import os
import threading
from typing import Any

from horizon._horizon import (
    Engine,
    EngineStatus,
    FeedSnapshot,
    Fill,
    Market,
    Order,
    OrderRequest,
    OrderSide,
    Position,
    Side,
    ContingentOrder,
)
from horizon.discovery import discover_markets, discover_events, top_markets
from horizon.flow import (
    get_market_trades as _get_market_trades,
    get_wallet_trades as _get_wallet_trades,
    get_wallet_positions as _get_wallet_positions,
    get_wallet_value as _get_wallet_value,
    get_top_holders as _get_top_holders,
    get_wallet_profile as _get_wallet_profile,
    analyze_market_flow as _analyze_market_flow,
)

_engine: Engine | None = None
_engine_lock = threading.Lock()


def get_engine() -> Engine:
    """Lazy-init a singleton Engine from environment variables."""
    global _engine
    if _engine is not None:
        return _engine

    with _engine_lock:
        # Double-check after acquiring lock
        if _engine is not None:
            return _engine

        exchange = os.environ.get("HORIZON_EXCHANGE", "paper")
        db_path = os.environ.get("HORIZON_DB") or None

        kwargs: dict[str, Any] = {
            "exchange_type": exchange,
            "db_path": db_path,
            "api_key": os.environ.get("HORIZON_API_KEY"),
        }

        if exchange == "polymarket":
            kwargs["exchange_key"] = os.environ.get("POLYMARKET_API_KEY")
            kwargs["exchange_secret"] = os.environ.get("POLYMARKET_API_SECRET")
            kwargs["exchange_passphrase"] = os.environ.get("POLYMARKET_API_PASSPHRASE")
            kwargs["private_key"] = os.environ.get("POLYMARKET_PRIVATE_KEY")
            kwargs["clob_url"] = os.environ.get("POLYMARKET_CLOB_URL")
        elif exchange == "kalshi":
            kwargs["email"] = os.environ.get("KALSHI_EMAIL")
            kwargs["password"] = os.environ.get("KALSHI_PASSWORD")
            kwargs["exchange_key"] = os.environ.get("KALSHI_API_KEY")
            kwargs["api_url"] = os.environ.get("KALSHI_API_URL")

        _engine = Engine(**kwargs)
        return _engine


def reset_engine() -> None:
    """Reset the singleton engine (for testing)."""
    global _engine
    with _engine_lock:
        _engine = None


# ---------------------------------------------------------------------------
# Serialization helpers
# ---------------------------------------------------------------------------

def _status_to_dict(s: EngineStatus) -> dict:
    return {
        "running": s.running,
        "kill_switch_active": s.kill_switch_active,
        "kill_switch_reason": s.kill_switch_reason,
        "open_orders": s.open_orders,
        "active_positions": s.active_positions,
        "total_realized_pnl": round(s.total_realized_pnl, 6),
        "total_unrealized_pnl": round(s.total_unrealized_pnl, 6),
        "daily_pnl": round(s.daily_pnl, 6),
        "uptime_secs": s.uptime_secs,
    }


def _position_to_dict(p: Position) -> dict:
    return {
        "market_id": p.market_id,
        "side": "yes" if p.side == Side.Yes else "no",
        "size": round(p.size, 6),
        "avg_entry_price": round(p.avg_entry_price, 6),
        "realized_pnl": round(p.realized_pnl, 6),
        "unrealized_pnl": round(p.unrealized_pnl, 6),
        "exchange": p.exchange,
    }


def _order_to_dict(o: Order) -> dict:
    return {
        "id": o.id,
        "market_id": o.market_id,
        "side": "yes" if o.side == Side.Yes else "no",
        "order_side": "buy" if o.order_side == OrderSide.Buy else "sell",
        "price": round(o.price, 6),
        "size": round(o.size, 6),
        "filled_size": round(o.filled_size, 6),
        "remaining_size": round(o.remaining_size, 6),
        "status": str(o.status),
        "exchange": o.exchange,
        "created_at": o.created_at,
    }


def _fill_to_dict(f: Fill) -> dict:
    return {
        "fill_id": f.fill_id,
        "order_id": f.order_id,
        "market_id": f.market_id,
        "side": "yes" if f.side == Side.Yes else "no",
        "order_side": "buy" if f.order_side == OrderSide.Buy else "sell",
        "price": round(f.price, 6),
        "size": round(f.size, 6),
        "fee": round(f.fee, 6),
        "timestamp": f.timestamp,
        "exchange": f.exchange,
    }


def _feed_to_dict(name: str, s: FeedSnapshot) -> dict:
    d = {
        "name": name,
        "price": round(s.price, 6),
        "bid": round(s.bid, 6),
        "ask": round(s.ask, 6),
        "volume_24h": round(s.volume_24h, 2),
        "source": s.source,
        "timestamp": s.timestamp,
    }
    if hasattr(s, "last_trade_size"):
        d["last_trade_size"] = round(s.last_trade_size, 6)
        d["last_trade_is_buy"] = s.last_trade_is_buy
    return d


def _market_to_dict(m: Market) -> dict:
    return {
        "id": m.id,
        "name": m.name,
        "slug": m.slug,
        "exchange": m.exchange,
        "expiry": m.expiry,
        "active": m.active,
    }


def _contingent_to_dict(c: ContingentOrder) -> dict:
    return {
        "id": c.id,
        "trigger_type": str(c.trigger_type),
        "market_id": c.market_id,
        "side": "yes" if c.side == Side.Yes else "no",
        "order_side": "buy" if c.order_side == OrderSide.Buy else "sell",
        "size": round(c.size, 6),
        "trigger_price": round(c.trigger_price, 6),
        "trigger_pnl": c.trigger_pnl,
        "exchange": c.exchange,
        "triggered": c.triggered,
        "child_order_id": c.child_order_id,
    }


# ---------------------------------------------------------------------------
# Tool functions - each returns dict | list[dict] | str
# ---------------------------------------------------------------------------

def engine_status() -> dict:
    """Get trading engine status."""
    try:
        return _status_to_dict(get_engine().status())
    except Exception as e:
        return {"error": str(e)}


def list_positions() -> list[dict] | dict:
    """List all open positions."""
    try:
        return [_position_to_dict(p) for p in get_engine().positions()]
    except Exception as e:
        return {"error": str(e)}


def list_open_orders(market_id: str | None = None) -> list[dict] | dict:
    """List open orders, optionally filtered by market."""
    try:
        eng = get_engine()
        if market_id:
            orders = eng.open_orders_for_market(market_id)
        else:
            orders = eng.open_orders()
        return [_order_to_dict(o) for o in orders]
    except Exception as e:
        return {"error": str(e)}


def list_recent_fills(limit: int = 20) -> list[dict] | dict:
    """List recent fills."""
    try:
        fills = get_engine().recent_fills()
        return [_fill_to_dict(f) for f in fills[-limit:]]
    except Exception as e:
        return {"error": str(e)}


def submit_order(
    market_id: str, side: str, price: float, size: float, market_side: str = "yes",
) -> dict:
    """Submit a limit order. side: 'buy' or 'sell'. market_side: 'yes' or 'no'."""
    try:
        if not (0.0 < price < 1.0):
            return {"error": f"price must be between 0 and 1 (exclusive), got {price}"}
        if not (size > 0) or math.isnan(size):
            return {"error": f"size must be a positive number, got {size}"}
        order_side = OrderSide.Buy if side.lower() == "buy" else OrderSide.Sell
        ms = Side.Yes if market_side.lower() == "yes" else Side.No
        req = OrderRequest(
            market_id=market_id,
            side=ms,
            order_side=order_side,
            size=size,
            price=price,
        )
        order_id = get_engine().submit_order(req)
        return {
            "order_id": order_id, "market_id": market_id, "side": side,
            "market_side": market_side, "price": price, "size": size,
        }
    except Exception as e:
        return {"error": str(e)}


def cancel_order(order_id: str) -> dict:
    """Cancel a single order by ID."""
    try:
        get_engine().cancel(order_id)
        return {"canceled": order_id}
    except Exception as e:
        return {"error": str(e)}


def cancel_all_orders() -> dict:
    """Cancel all open orders."""
    try:
        count = get_engine().cancel_all()
        return {"canceled_count": count}
    except Exception as e:
        return {"error": str(e)}


def cancel_market_orders(market_id: str) -> dict:
    """Cancel all orders for a specific market."""
    try:
        count = get_engine().cancel_market(market_id)
        return {"market_id": market_id, "canceled_count": count}
    except Exception as e:
        return {"error": str(e)}


def activate_kill_switch(reason: str) -> dict:
    """Activate the kill switch - emergency stop. Cancels all orders."""
    try:
        get_engine().activate_kill_switch(reason)
        return {"kill_switch": "activated", "reason": reason}
    except Exception as e:
        return {"error": str(e)}


def deactivate_kill_switch() -> dict:
    """Deactivate the kill switch - resume trading."""
    try:
        get_engine().deactivate_kill_switch()
        return {"kill_switch": "deactivated"}
    except Exception as e:
        return {"error": str(e)}


def get_feed_snapshot(name: str) -> dict:
    """Get price/bid/ask snapshot for a named feed."""
    try:
        snap = get_engine().feed_snapshot(name)
        if snap is None:
            return {"error": f"feed not found: {name}"}
        return _feed_to_dict(name, snap)
    except Exception as e:
        return {"error": str(e)}


def list_all_feeds() -> list[dict] | dict:
    """List all feed snapshots."""
    try:
        snapshots = get_engine().all_feed_snapshots()
        return [_feed_to_dict(name, snap) for name, snap in snapshots.items()]
    except Exception as e:
        return {"error": str(e)}


def discover(
    exchange: str = "polymarket",
    query: str = "",
    limit: int = 10,
    market_type: str = "all",
) -> list[dict] | dict:
    """Search for markets on an exchange.

    market_type: "all" (default), "binary", or "multi".
    """
    try:
        results: list[dict] = []

        if market_type in ("all", "binary"):
            markets = discover_markets(exchange=exchange, query=query, limit=limit)
            results.extend(_market_to_dict(m) for m in markets)

        if market_type in ("all", "multi") and exchange == "polymarket":
            events = discover_events(exchange="polymarket", query=query, limit=limit)
            for ev in events:
                outcomes = []
                for o in ev.outcomes:
                    outcomes.append({
                        "name": o.name,
                        "market_id": o.market_id,
                        "yes_price": round(o.yes_price, 4),
                    })
                results.append({
                    "id": ev.id,
                    "name": ev.name,
                    "type": "multi",
                    "outcome_count": len(outcomes),
                    "outcomes": outcomes,
                    "exchange": ev.exchange,
                    "condition_id": ev.condition_id,
                    "expiry": ev.expiry,
                })

        return results[:limit]
    except Exception as e:
        return {"error": str(e)}


def kelly_sizing(
    prob: float,
    price: float,
    bankroll: float = 1000.0,
    fraction: float = 0.25,
    max_size: float = 100.0,
) -> dict:
    """Compute Kelly-optimal position size."""
    try:
        from horizon._horizon import kelly_size, edge as kelly_edge

        size = kelly_size(prob, price, bankroll, fraction, max_size)
        e = kelly_edge(prob, price)
        return {
            "optimal_size": round(size, 4),
            "edge": round(e, 4),
            "prob": prob,
            "price": price,
            "bankroll": bankroll,
            "fraction": fraction,
        }
    except Exception as e:
        return {"error": str(e)}


def check_parity(market_id: str, feed_name: str | None = None) -> dict:
    """Check YES/NO price parity for a market. Optionally specify a feed_name."""
    try:
        if feed_name is not None:
            result = get_engine().parity_check(market_id, feed_name=feed_name)
        else:
            result = get_engine().parity_check(market_id)
        if result is None:
            return {"error": f"no parity data for market: {market_id}"}
        return {
            "market_id": result.market_id,
            "yes_price": round(result.yes_price, 6),
            "no_price": round(result.no_price, 6),
            "deviation": round(result.deviation, 6),
            "is_violation": result.is_violation,
            "exchange": result.exchange,
        }
    except Exception as e:
        return {"error": str(e)}


def feed_metrics(name: str) -> dict:
    """Get feed connection metrics (update count, errors, reconnects)."""
    try:
        m = get_engine().feed_metrics(name)
        if m is None:
            return {"error": f"no metrics for feed: {name}"}
        return {
            "name": name,
            "update_count": m.update_count,
            "error_count": m.error_count,
            "last_update_time": m.last_update_time,
            "last_error": m.last_error,
            "is_connected": m.is_connected,
            "reconnect_count": m.reconnect_count,
        }
    except Exception as e:
        return {"error": str(e)}


def all_feed_metrics() -> list[dict] | dict:
    """Get metrics for all active feeds."""
    try:
        metrics = get_engine().all_feed_metrics()
        return [
            {
                "name": name,
                "update_count": m.update_count,
                "error_count": m.error_count,
                "last_update_time": m.last_update_time,
                "last_error": m.last_error,
                "is_connected": m.is_connected,
                "reconnect_count": m.reconnect_count,
            }
            for name, m in metrics.items()
        ]
    except Exception as e:
        return {"error": str(e)}


def add_stop_loss(
    market_id: str,
    side: str,
    order_side: str,
    size: float,
    trigger: float,
) -> dict:
    """Add a stop-loss contingent order."""
    try:
        s = Side.Yes if side.lower() == "yes" else Side.No
        os_ = OrderSide.Buy if order_side.lower() == "buy" else OrderSide.Sell
        cid = get_engine().add_stop_loss(market_id, s, os_, size, trigger)
        return {"contingent_id": cid, "type": "stop_loss", "market_id": market_id}
    except Exception as e:
        return {"error": str(e)}


def add_take_profit(
    market_id: str,
    side: str,
    order_side: str,
    size: float,
    trigger: float,
) -> dict:
    """Add a take-profit contingent order."""
    try:
        s = Side.Yes if side.lower() == "yes" else Side.No
        os_ = OrderSide.Buy if order_side.lower() == "buy" else OrderSide.Sell
        cid = get_engine().add_take_profit(market_id, s, os_, size, trigger)
        return {"contingent_id": cid, "type": "take_profit", "market_id": market_id}
    except Exception as e:
        return {"error": str(e)}


def list_contingent_orders() -> list[dict] | dict:
    """List pending stop-loss and take-profit orders."""
    try:
        return [_contingent_to_dict(c) for c in get_engine().pending_contingent_orders()]
    except Exception as e:
        return {"error": str(e)}


# ---------------------------------------------------------------------------
# Discovery tools
# ---------------------------------------------------------------------------

def discover_event(
    query: str = "",
    limit: int = 10,
    min_volume: float = 0.0,
) -> list[dict] | dict:
    """Discover multi-outcome events on Polymarket."""
    try:
        events = discover_events(
            exchange="polymarket", query=query,
            active=True, limit=limit, min_volume=min_volume,
        )
        results = []
        for ev in events:
            outcomes = []
            for o in ev.outcomes:
                outcomes.append({
                    "name": o.name,
                    "market_id": o.market_id,
                    "yes_price": round(o.yes_price, 4),
                })
            results.append({
                "id": ev.id,
                "name": ev.name,
                "outcome_count": len(outcomes),
                "outcomes": outcomes,
                "exchange": ev.exchange,
                "condition_id": ev.condition_id,
                "expiry": ev.expiry,
            })
        return results
    except Exception as e:
        return {"error": str(e)}


def market_detail(slug_or_id: str, exchange: str = "polymarket") -> dict:
    """Fetch comprehensive detail for a single market."""
    try:
        from horizon.discovery import get_market_detail
        return get_market_detail(slug_or_id, exchange=exchange)
    except Exception as e:
        return {"error": str(e)}


def get_top_markets(
    exchange: str = "polymarket",
    limit: int = 10,
    category: str = "",
) -> list[dict] | dict:
    """Get top markets by volume."""
    try:
        markets = top_markets(exchange=exchange, limit=limit, category=category)
        return [_market_to_dict(m) for m in markets]
    except Exception as e:
        return {"error": str(e)}


# ---------------------------------------------------------------------------
# Wallet analytics tools
# ---------------------------------------------------------------------------

def wallet_trades(
    address: str,
    limit: int = 50,
    condition_id: str | None = None,
) -> list[dict] | dict:
    """Fetch trade history for a Polymarket wallet."""
    try:
        trades = _get_wallet_trades(address, limit=limit, condition_id=condition_id)
        return [
            {
                "wallet": t.wallet,
                "side": t.side,
                "outcome": t.outcome,
                "size": round(t.size, 4),
                "price": round(t.price, 4),
                "usdc_size": round(t.usdc_size, 2),
                "timestamp": t.timestamp,
                "market_slug": t.market_slug,
                "market_title": t.market_title,
                "pseudonym": t.pseudonym,
            }
            for t in trades
        ]
    except Exception as e:
        return {"error": str(e)}


def market_trades(
    condition_id: str,
    limit: int = 50,
    side: str | None = None,
    min_size: float = 0.0,
) -> list[dict] | dict:
    """Fetch recent trades for a Polymarket market."""
    try:
        trades = _get_market_trades(
            condition_id, limit=limit, side=side, min_size=min_size,
        )
        return [
            {
                "wallet": t.wallet,
                "side": t.side,
                "outcome": t.outcome,
                "size": round(t.size, 4),
                "price": round(t.price, 4),
                "usdc_size": round(t.usdc_size, 2),
                "timestamp": t.timestamp,
                "market_title": t.market_title,
                "pseudonym": t.pseudonym,
            }
            for t in trades
        ]
    except Exception as e:
        return {"error": str(e)}


def wallet_positions(
    address: str,
    limit: int = 50,
    sort_by: str = "CURRENT",
) -> list[dict] | dict:
    """Fetch open positions for a Polymarket wallet."""
    try:
        positions = _get_wallet_positions(address, limit=limit, sort_by=sort_by)
        return [
            {
                "market_title": p.market_title,
                "market_slug": p.market_slug,
                "outcome": p.outcome,
                "size": round(p.size, 4),
                "avg_price": round(p.avg_price, 4),
                "current_price": round(p.current_price, 4),
                "current_value": round(p.current_value, 2),
                "pnl": round(p.pnl, 2),
                "pnl_percent": round(p.pnl_percent, 2),
            }
            for p in positions
        ]
    except Exception as e:
        return {"error": str(e)}


def wallet_value(address: str) -> dict:
    """Get total USD value of a Polymarket wallet's positions."""
    try:
        value = _get_wallet_value(address)
        return {"wallet": address, "total_value_usd": round(value, 2)}
    except Exception as e:
        return {"error": str(e)}


def wallet_profile(address: str) -> dict:
    """Get public profile for a Polymarket wallet."""
    try:
        profile = _get_wallet_profile(address)
        if profile is None:
            return {"error": f"no profile found for {address}"}
        return {
            "wallet": profile.wallet,
            "pseudonym": profile.pseudonym,
            "name": profile.name,
            "bio": profile.bio,
            "profile_image": profile.profile_image,
            "x_username": profile.x_username,
            "created_at": profile.created_at,
        }
    except Exception as e:
        return {"error": str(e)}


def market_top_holders(condition_id: str, limit: int = 20) -> list[dict] | dict:
    """Get top holders for a Polymarket market."""
    try:
        holders = _get_top_holders(condition_id, limit=limit)
        return [
            {
                "wallet": h.wallet,
                "amount": round(h.amount, 4),
                "token_id": h.token_id,
                "outcome_index": h.outcome_index,
                "pseudonym": h.pseudonym,
                "name": h.name,
            }
            for h in holders
        ]
    except Exception as e:
        return {"error": str(e)}


def market_flow(
    condition_id: str,
    trade_limit: int = 500,
    top_n: int = 10,
) -> dict:
    """Analyze trade flow for a Polymarket market."""
    try:
        flow = _analyze_market_flow(
            condition_id, trade_limit=trade_limit, top_n=top_n,
        )
        return {
            "condition_id": flow.condition_id,
            "total_trades": flow.total_trades,
            "buy_volume": round(flow.buy_volume, 2),
            "sell_volume": round(flow.sell_volume, 2),
            "net_flow": round(flow.net_flow, 2),
            "unique_wallets": flow.unique_wallets,
            "top_buyers": [
                {"wallet": w, "volume": round(v, 2)} for w, v in flow.top_buyers
            ],
            "top_sellers": [
                {"wallet": w, "volume": round(v, 2)} for w, v in flow.top_sellers
            ],
        }
    except Exception as e:
        return {"error": str(e)}


# ---------------------------------------------------------------------------
# Feed health tools
# ---------------------------------------------------------------------------

def start_feed(
    name: str,
    feed_type: str,
    config_json: str | None = None,
    symbol: str | None = None,
    url: str | None = None,
    interval: float = 5.0,
) -> dict:
    """Start a live data feed on the engine.

    For newer feed types (predictit, manifold, espn, nws, rest_json_path,
    chainlink), pass structured config via ``config_json``.
    For legacy types (binance_ws, polymarket_book, kalshi_book, rest),
    use the keyword arguments.
    """
    try:
        kwargs: dict[str, Any] = {}
        if symbol is not None:
            kwargs["symbol"] = symbol
        if url is not None:
            kwargs["url"] = url
        kwargs["interval"] = interval
        if config_json is not None:
            kwargs["config_json"] = config_json
        get_engine().start_feed(name, feed_type, **kwargs)
        return {"started": name, "feed_type": feed_type}
    except Exception as e:
        return {"error": str(e)}


def check_feed_health(stale_threshold: float = 30.0) -> dict:
    """Check staleness and health of all active feeds."""
    try:
        import time
        snapshots = get_engine().all_feed_snapshots()
        now = time.time()
        feeds = {}
        stale_count = 0
        for name, snap in snapshots.items():
            age = now - snap.timestamp if snap.timestamp > 0 else float("inf")
            is_stale = age > stale_threshold or snap.timestamp <= 0
            if is_stale:
                stale_count += 1
            feeds[name] = {
                "name": name,
                "is_stale": is_stale,
                "age_secs": round(age, 1),
                "price": round(snap.price, 6),
                "bid": round(snap.bid, 6),
                "ask": round(snap.ask, 6),
            }
        return {
            "feeds": feeds,
            "total_feeds": len(feeds),
            "stale_count": stale_count,
            "all_stale": stale_count == len(feeds) and len(feeds) > 0,
            "stale_threshold_secs": stale_threshold,
        }
    except Exception as e:
        return {"error": str(e)}


# ---------------------------------------------------------------------------
# Simulation tools
# ---------------------------------------------------------------------------

def simulate_portfolio(
    scenarios: int = 10000,
    seed: int | None = None,
) -> dict:
    """Run Monte Carlo simulation on the engine's current positions."""
    try:
        from horizon.simulate import simulate
        result = simulate(engine=get_engine(), scenarios=scenarios, seed=seed)
        return {
            "mean_pnl": round(result.mean_pnl, 2),
            "median_pnl": round(result.median_pnl, 2),
            "std_dev": round(result.std_dev, 2),
            "var_95": round(result.var_95, 2),
            "var_99": round(result.var_99, 2),
            "cvar_95": round(result.cvar_95, 2),
            "max_loss": round(result.max_loss, 2),
            "max_gain": round(result.max_gain, 2),
            "win_probability": round(result.win_probability, 4),
            "scenarios": scenarios,
        }
    except Exception as e:
        return {"error": str(e)}


# ---------------------------------------------------------------------------
# Arbitrage tools
# ---------------------------------------------------------------------------

def execute_arb(
    market_id: str,
    buy_exchange: str,
    sell_exchange: str,
    buy_price: float,
    sell_price: float,
    size: float,
) -> dict:
    """Execute a cross-exchange arbitrage trade with atomic rollback."""
    try:
        buy_id, sell_id = get_engine().execute_arbitrage(
            market_id, buy_exchange, sell_exchange,
            buy_price=buy_price, sell_price=sell_price, size=size,
        )
        return {
            "buy_order_id": buy_id,
            "sell_order_id": sell_id,
            "market_id": market_id,
            "buy_exchange": buy_exchange,
            "sell_exchange": sell_exchange,
            "buy_price": buy_price,
            "sell_price": sell_price,
            "size": size,
        }
    except Exception as e:
        return {"error": str(e)}


# ---------------------------------------------------------------------------
# Quantitative analytics tools
# ---------------------------------------------------------------------------

def compute_shannon_entropy(p: float) -> dict:
    """Compute binary Shannon entropy for a probability."""
    try:
        from horizon._horizon import shannon_entropy
        return {"entropy": round(shannon_entropy(p), 6), "probability": p}
    except Exception as e:
        return {"error": str(e)}


def compute_kl_divergence(p: list[float], q: list[float]) -> dict:
    """Compute KL divergence between two probability distributions."""
    try:
        from horizon._horizon import kl_divergence
        return {"kl_divergence": round(kl_divergence(p, q), 6)}
    except Exception as e:
        return {"error": str(e)}


def compute_hurst_exponent(prices: list[float]) -> dict:
    """Compute Hurst exponent for a price series. >0.5 trending, <0.5 mean-reverting."""
    try:
        from horizon._horizon import hurst_exponent
        h = hurst_exponent(prices)
        regime = "trending" if h > 0.55 else "mean-reverting" if h < 0.45 else "random walk"
        return {"hurst": round(h, 4), "regime": regime}
    except Exception as e:
        return {"error": str(e)}


def compute_variance_ratio(returns: list[float], period: int = 2) -> dict:
    """Variance ratio test. 1.0 = random walk."""
    try:
        from horizon._horizon import variance_ratio
        vr = variance_ratio(returns, period)
        is_efficient = 0.8 <= vr <= 1.2
        return {"variance_ratio": round(vr, 4), "period": period, "is_efficient": is_efficient}
    except Exception as e:
        return {"error": str(e)}


def compute_cornish_fisher_var(returns: list[float], confidence: float = 0.95) -> dict:
    """Cornish-Fisher VaR/CVaR (skew/kurtosis-adjusted)."""
    try:
        from horizon._horizon import cornish_fisher_var, cornish_fisher_cvar
        var = cornish_fisher_var(returns, confidence)
        cvar = cornish_fisher_cvar(returns, confidence)
        return {
            "var": round(var, 6),
            "cvar": round(cvar, 6),
            "confidence": confidence,
            "n_observations": len(returns),
        }
    except Exception as e:
        return {"error": str(e)}


def compute_prediction_greeks(
    price: float,
    size: float,
    is_yes: bool = True,
    t_hours: float = 24.0,
    vol: float = 0.2,
) -> dict:
    """Compute prediction Greeks (delta, gamma, theta, vega) for a binary market position."""
    try:
        from horizon._horizon import prediction_greeks
        g = prediction_greeks(price, size, is_yes, t_hours, vol)
        return {
            "delta": round(g.delta, 6),
            "gamma": round(g.gamma, 6),
            "theta": round(g.theta, 6),
            "vega": round(g.vega, 6),
            "price": price,
            "size": size,
        }
    except Exception as e:
        return {"error": str(e)}


def compute_deflated_sharpe(
    sharpe: float,
    n_obs: int,
    n_trials: int,
    skew: float = 0.0,
    kurt: float = 3.0,
) -> dict:
    """Deflated Sharpe Ratio: tests if observed Sharpe is statistically significant given multiple trials."""
    try:
        from horizon._horizon import deflated_sharpe, bonferroni_threshold
        p_value = deflated_sharpe(sharpe, n_obs, n_trials, skew, kurt)
        bonf = bonferroni_threshold(0.05, n_trials)
        return {
            "p_value": round(p_value, 6),
            "is_significant": p_value < 0.05,
            "bonferroni_alpha": round(bonf, 6),
            "sharpe": sharpe,
            "n_obs": n_obs,
            "n_trials": n_trials,
        }
    except Exception as e:
        return {"error": str(e)}


def run_signal_diagnostics(predictions: list[float], outcomes: list[float]) -> dict:
    """Run signal diagnostics: information coefficient, half-life, Hurst exponent."""
    try:
        from horizon.quant import signal_diagnostics
        return signal_diagnostics(predictions, outcomes)
    except Exception as e:
        return {"error": str(e)}


def run_market_efficiency(prices: list[float]) -> dict:
    """Analyze market efficiency: variance ratio, Hurst exponent, efficiency flag."""
    try:
        from horizon.quant import market_efficiency
        return market_efficiency(prices)
    except Exception as e:
        return {"error": str(e)}


def run_stress_test(
    n_simulations: int = 10000,
    seed: int | None = None,
) -> dict:
    """Run stress test on current engine positions under adverse scenarios."""
    try:
        from horizon._horizon import SimPosition
        from horizon.stress import stress_test, CORRELATION_SPIKE, ALL_RESOLVE_NO, LIQUIDITY_SHOCK, TAIL_RISK

        eng = get_engine()
        positions = eng.positions()
        if not positions:
            return {"error": "no open positions to stress test"}

        sim_positions = []
        feeds = eng.all_feed_snapshots()
        for p in positions:
            price = 0.5
            snap = feeds.get(p.market_id)
            if snap is not None:
                price = snap.price
            sim_positions.append(SimPosition(
                p.market_id,
                "yes" if p.side == Side.Yes else "no",
                p.size,
                p.avg_entry_price,
                price,
            ))

        result = stress_test(sim_positions, n_simulations=n_simulations, seed=seed)
        return {
            "worst_scenario": result.worst_scenario,
            "worst_pnl": round(result.worst_pnl, 2),
            "scenarios": [
                {
                    "name": s.scenario.name,
                    "mean_pnl": round(s.sim.mean_pnl, 2),
                    "var_95": round(s.sim.var_95, 2),
                    "worst_pnl": round(s.sim.max_loss, 2),
                }
                for s in result.scenarios
            ],
        }
    except Exception as e:
        return {"error": str(e)}
