"""实盘/关键位放大 K 线:订单元数据与交易所浮盈,价格展示精度."""
from __future__ import annotations

from typing import Any, Callable, Optional

from lib.hub.hub_ohlcv_lib import (
    normalize_price_tick,
    price_tick_from_market,
    round_ohlcv_bars_to_tick,
)
from lib.trade.order_monitor_display_lib import (
    apply_order_live_price_display,
    apply_order_price_display_fields,
)


def resolve_kline_price_tick(
    exchange: Any,
    exchange_symbol: str,
    *,
    ensure_markets_fn: Callable[[], None],
) -> Optional[float]:
    """交易所最小价格变动单位,供 lightweight-charts 右侧刻度与标记线对齐."""
    if not exchange_symbol:
        return None
    try:
        ensure_markets_fn()
        return normalize_price_tick(price_tick_from_market(exchange, exchange_symbol))
    except Exception:
        return None


def align_candles_to_price_tick(
    candles: list[dict[str, Any]],
    price_tick: Optional[float],
) -> None:
    if price_tick is not None and candles:
        round_ohlcv_bars_to_tick(candles, price_tick)


def kline_api_price_fields(
    exchange: Any,
    exchange_symbol: str,
    candles: list[dict[str, Any]],
    *,
    ensure_markets_fn: Callable[[], None],
) -> dict[str, Any]:
    tick = resolve_kline_price_tick(
        exchange, exchange_symbol, ensure_markets_fn=ensure_markets_fn
    )
    align_candles_to_price_tick(candles, tick)
    return {"price_tick": tick}


def load_swap_positions_for_order_kline(
    exchange: Any,
    *,
    private_configured: bool,
    ensure_markets_fn: Callable[[], None],
    settle: str = "usdt",
) -> list:
    if not private_configured:
        return []
    try:
        ensure_markets_fn()
        try:
            return exchange.fetch_positions(None, {"settle": settle}) or []
        except Exception:
            return exchange.fetch_positions() or []
    except Exception:
        return []


def metrics_for_order_item(
    order_item: dict[str, Any],
    positions: list,
    *,
    resolve_ex_sym_fn: Callable[[Any], str],
    select_live_fn: Callable[[list, str, str], Any],
    parse_metrics_fn: Callable[..., Optional[dict]],
) -> Optional[dict]:
    if not positions:
        return None
    ex_sym = resolve_ex_sym_fn(order_item)
    direction = order_item.get("direction") or "long"
    prow = select_live_fn(positions, ex_sym, direction)
    if not prow:
        return None
    lev = order_item.get("leverage")
    return parse_metrics_fn(prow, order_leverage=lev)


def build_order_kline_order_payload(
    order_item: dict[str, Any],
    *,
    ticker_price: Any,
    format_price_fn: Callable[[Any, Any], str],
    calc_pnl_fn: Callable[..., float],
    calc_rr_ratio_fn: Callable[..., Optional[float]],
    ex_metrics: Optional[dict] = None,
) -> dict[str, Any]:
    sym = order_item.get("symbol") or ""
    direction = order_item.get("direction") or "long"
    margin = float(order_item.get("margin_capital") or 0)
    leverage = float(order_item.get("leverage") or 0)
    entry = float(order_item.get("trigger_price") or 0)

    float_pnl = 0.0
    float_pct = 0.0
    if ticker_price and entry > 0:
        float_pnl = float(
            calc_pnl_fn(direction, entry, ticker_price, margin, leverage)
        )
        float_pct = round((float_pnl / margin * 100), 4) if margin > 0 else 0.0

    px_for_fmt = ticker_price
    mark_raw = None
    if ex_metrics and ex_metrics.get("mark_price") is not None:
        mark_raw = ex_metrics["mark_price"]
        try:
            px_for_fmt = float(mark_raw)
        except (TypeError, ValueError):
            pass

    if ex_metrics and ex_metrics.get("unrealized_pnl") is not None:
        float_pnl = round(float(ex_metrics["unrealized_pnl"]), 2)
        denom = ex_metrics.get("initial_margin") or margin
        float_pct = (
            round((float_pnl / float(denom)) * 100, 4)
            if denom and float(denom) > 0
            else float_pct
        )

    payload: dict[str, Any] = {
        "id": order_item["id"],
        "symbol": sym,
        "direction": direction,
        "trigger_price": order_item.get("trigger_price"),
        "stop_loss": order_item.get("stop_loss"),
        "take_profit": order_item.get("take_profit"),
        "trigger_price_display": format_price_fn(sym, order_item.get("trigger_price")),
        "stop_loss_display": format_price_fn(sym, order_item.get("stop_loss")),
        "take_profit_display": format_price_fn(sym, order_item.get("take_profit")),
        "margin_capital": order_item.get("margin_capital"),
        "leverage": order_item.get("leverage"),
        "position_ratio": order_item.get("position_ratio"),
        "breakeven_enabled": bool(int(order_item.get("breakeven_enabled") or 0)),
        "current_price": round(float(px_for_fmt), 8) if px_for_fmt is not None else None,
        "float_pnl": round(float(float_pnl), 2),
        "float_pct": float_pct,
    }
    apply_order_price_display_fields(
        payload,
        direction=direction,
        entry_price=order_item.get("trigger_price"),
        initial_stop_loss=order_item.get("initial_stop_loss"),
        stop_loss=order_item.get("stop_loss"),
        take_profit=order_item.get("take_profit"),
        calc_rr_ratio_fn=calc_rr_ratio_fn,
    )
    apply_order_live_price_display(
        payload,
        sym,
        ticker_price,
        mark_raw,
        format_price_fn,
    )
    payload["current_price_display"] = payload.get("price_display") or (
        format_price_fn(sym, px_for_fmt) if px_for_fmt is not None else None
    )
    return payload


def enrich_key_kline_response(
    *,
    symbol: str,
    current_price: Any,
    key_info: Optional[dict[str, Any]],
    format_price_fn: Callable[[Any, Any], str],
) -> tuple[Any, Optional[dict[str, Any]]]:
    price_display = format_price_fn(symbol, current_price) if current_price is not None else None
    if key_info is None:
        return price_display, None
    enriched = dict(key_info)
    enriched["upper_display"] = format_price_fn(symbol, key_info.get("upper"))
    enriched["lower_display"] = format_price_fn(symbol, key_info.get("lower"))
    return price_display, enriched
