"""实例页:持仓未实现盈亏(实时盈亏)汇总."""
from __future__ import annotations

from collections.abc import Callable
from typing import Any

from lib.hub.hub_position_metrics import parse_position_unrealized_pnl


def position_row_contracts(pos: dict[str, Any]) -> float:
    """持仓张数:与三所 app 内 _position_row_effective_contracts 规则一致."""
    if not isinstance(pos, dict):
        return 0.0
    info = pos.get("info") or {}
    if not isinstance(info, dict):
        info = {}
    for val in (
        pos.get("contracts"),
        info.get("positionAmt"),
        info.get("size"),
        info.get("pos"),
        info.get("availPos"),
    ):
        if val is None or val == "":
            continue
        try:
            x = abs(float(val))
            if x > 0:
                return x
        except (TypeError, ValueError):
            continue
    return 0.0


def sum_unrealized_pnl_from_positions(positions: list[dict[str, Any]] | None) -> float | None:
    total = 0.0
    found = False
    for p in positions or []:
        if not isinstance(p, dict):
            continue
        if position_row_contracts(p) <= 1e-12:
            continue
        upnl = parse_position_unrealized_pnl(p)
        if upnl is None:
            continue
        found = True
        total += float(upnl)
    return round(total, 2) if found else None


def _row_field(row: Any, key: str, default: str = "") -> str:
    if row is None:
        return default
    try:
        if hasattr(row, "keys") and key in row.keys():
            val = row[key]
        elif isinstance(row, dict):
            val = row.get(key)
        else:
            val = None
    except Exception:
        val = None
    return str(val or default).strip()


def sum_unrealized_pnl_from_metrics(
    rows: list[dict[str, Any]] | list[Any],
    get_metrics_fn: Callable[[str, str], dict[str, Any] | None],
) -> float | None:
    """按活跃监控单逐笔拉交易所 metrics 汇总(与持仓卡浮盈亏一致)."""
    total = 0.0
    found = False
    for row in rows or []:
        ex_sym = _row_field(row, "exchange_symbol")
        sym = _row_field(row, "symbol")
        direction = _row_field(row, "direction", "long").lower() or "long"
        target = ex_sym or sym
        if not target:
            continue
        metrics = get_metrics_fn(target, direction)
        if not isinstance(metrics, dict):
            continue
        upnl = metrics.get("unrealized_pnl")
        if upnl is None:
            continue
        try:
            total += float(upnl)
            found = True
        except (TypeError, ValueError):
            continue
    return round(total, 2) if found else None


def fetch_unrealized_pnl(fetch_positions_fn: Callable[[], list[dict[str, Any]] | None]) -> float | None:
    try:
        return sum_unrealized_pnl_from_positions(fetch_positions_fn() or [])
    except Exception:
        return None


def resolve_instance_unrealized_pnl(
    fetch_positions_fn: Callable[[], list[dict[str, Any]] | None],
    active_rows: list[Any] | None,
    get_metrics_fn: Callable[[str, str], dict[str, Any] | None] | None,
) -> float | None:
    """先全量持仓汇总,失败或无数据时回退到活跃监控单 metrics."""
    total = fetch_unrealized_pnl(fetch_positions_fn)
    if total is not None:
        return total
    if active_rows and get_metrics_fn:
        return sum_unrealized_pnl_from_metrics(active_rows, get_metrics_fn)
    return None


def merge_unrealized_pnl_components(*parts: float | None) -> float | None:
    """合并永续与期权等多路未实现盈亏(任一路有值即参与合计)."""
    total = 0.0
    found = False
    for part in parts:
        if part is None:
            continue
        try:
            total += float(part)
            found = True
        except (TypeError, ValueError):
            continue
    return round(total, 2) if found else None
