"""price_snapshot 共用:订单行情价兜底,避免 get_price 失败时整单不入 order_prices."""
from __future__ import annotations

from typing import Any, Callable, Mapping, Optional, Sequence

from lib.hub.hub_position_metrics import parse_position_mark_price


def resolve_order_snapshot_price(
    symbol: str,
    prices: Mapping[str, float],
    *,
    position_row: Optional[dict[str, Any]] = None,
    order_leverage=None,
    parse_position_metrics_fn: Callable[..., dict[str, Any] | None] | None = None,
    get_mark_price_fn: Callable[[str], float | None] | None = None,
    fallback_entry: float | None = None,
) -> float | None:
    """
    解析下单监控轮询用的现价/标记价,优先级:
    1. 已批量拉取的 ticker last
    2. get_symbol_mark_price(含 mark)
    3. 交易所持仓 mark(parse_ccxt_position_metrics / parse_position_mark_price)
    4. 计划成交价 trigger_price
    """
    sym = (symbol or "").strip()
    if not sym:
        return None

    cached = prices.get(sym)
    if cached is not None:
        try:
            v = float(cached)
            if v > 0:
                return v
        except (TypeError, ValueError):
            pass

    if get_mark_price_fn is not None:
        try:
            mp = get_mark_price_fn(sym)
            if mp is not None and float(mp) > 0:
                return float(mp)
        except Exception:
            pass

    if position_row:
        mark = None
        if parse_position_metrics_fn is not None:
            try:
                metrics = parse_position_metrics_fn(
                    position_row, order_leverage=order_leverage
                )
                if isinstance(metrics, dict) and metrics.get("mark_price") is not None:
                    mark = float(metrics["mark_price"])
            except Exception:
                mark = None
        if mark is None or mark <= 0:
            try:
                mp = parse_position_mark_price(position_row)
                if mp is not None and mp > 0:
                    mark = float(mp)
            except Exception:
                mark = None
        if mark is not None and mark > 0:
            return mark

    if fallback_entry is not None:
        try:
            entry = float(fallback_entry)
            if entry > 0:
                return entry
        except (TypeError, ValueError):
            pass
    return None


def seed_prices_from_positions(
    prices: dict[str, float],
    order_rows: Sequence[Any],
    all_positions: Sequence[dict[str, Any]],
    *,
    resolve_ex_sym_fn: Callable[[Any], str],
) -> None:
    """用持仓标记价补全 prices 字典(symbol 与 order_monitors 行对齐)."""
    if not all_positions or not order_rows:
        return
    try:
        from lib.hub.hub_symbol_lib import symbols_match
    except Exception:
        symbols_match = None
    for r in order_rows:
        try:
            sym = str(r["symbol"] or "").strip()
        except (KeyError, TypeError, IndexError):
            sym = ""
        if not sym or sym in prices:
            continue
        try:
            ex_sym = resolve_ex_sym_fn(r)
        except Exception:
            ex_sym = sym
        try:
            direction = str(r["direction"] or "long").lower()
        except (KeyError, TypeError, IndexError):
            direction = "long"
        for p in all_positions:
            if not isinstance(p, dict):
                continue
            ps = p.get("symbol") or ""
            if not ps:
                continue
            matched = ps == sym or ps == ex_sym
            if not matched and symbols_match is not None:
                matched = symbols_match(sym, ps) or symbols_match(ex_sym, ps)
            if not matched:
                continue
            side = (p.get("side") or "").lower()
            if side and side != direction:
                continue
            mp = parse_position_mark_price(p)
            if mp is not None and mp > 0:
                prices[sym] = float(mp)
                break
