"""监控区看板:三所当日统计聚合."""
from __future__ import annotations

from typing import Any

from lib.hub.hub_options_funds_lib import (
    options_float_pnl_usdt,
    options_open_position_count as count_options_positions,
)


def _coerce_float(value: Any) -> float | None:
    if value is None or value == "":
        return None
    try:
        return float(value)
    except (TypeError, ValueError):
        return None


def position_unrealized_pnl(pos: dict[str, Any]) -> float:
    for key in ("unrealized_pnl", "unrealizedPnl", "upnl"):
        v = _coerce_float(pos.get(key))
        if v is not None:
            return v
    return 0.0


def _open_positions(agent: dict[str, Any] | None) -> list[dict[str, Any]]:
    if not isinstance(agent, dict):
        return []
    positions = agent.get("positions")
    if not isinstance(positions, list):
        return []
    out: list[dict[str, Any]] = []
    for p in positions:
        if not isinstance(p, dict):
            continue
        try:
            c = abs(float(p.get("contracts") or 0))
        except (TypeError, ValueError):
            c = 0.0
        if c > 1e-12:
            out.append(p)
    return out


def aggregate_monitor_board_totals(
    rows: list[dict[str, Any]],
    *,
    trading_day: str,
    reset_hour: int = 8,
) -> dict[str, Any]:
    """汇总监控 board 各行 → 左上统计卡数据."""
    open_count = 0
    closed_count = 0
    win_count = 0
    loss_count = 0
    win_pnl_u = 0.0
    loss_pnl_u = 0.0
    open_position_count = 0
    options_open_position_count = 0
    float_pnl_u = 0.0
    options_float_pnl_u = 0.0

    for row in rows or []:
        if not isinstance(row, dict):
            continue
        day_stats = row.get("day_stats") if isinstance(row.get("day_stats"), dict) else {}
        if day_stats.get("ok"):
            open_count += int(day_stats.get("opens_today") or 0)
            st = day_stats.get("trade_stats") if isinstance(day_stats.get("trade_stats"), dict) else {}
            closed_count += int(st.get("closed_count") or 0)
            win_count += int(st.get("win_count") or 0)
            loss_count += int(st.get("loss_count") or 0)
            win_pnl_u += float(st.get("win_pnl_u") or 0)
            loss_pnl_u += float(st.get("loss_pnl_u") or 0)

        ag = row.get("agent") if isinstance(row.get("agent"), dict) else {}
        open_pos = _open_positions(ag)
        open_position_count += len(open_pos)
        agent_upnl = _coerce_float(ag.get("total_unrealized_pnl"))
        if agent_upnl is not None:
            float_pnl_u += agent_upnl
        else:
            float_pnl_u += sum(position_unrealized_pnl(p) for p in open_pos)

        opt_snap = row.get("options") if "options" in (row.get("capabilities") or []) else None
        opt_count = count_options_positions(opt_snap)
        options_open_position_count += opt_count
        open_position_count += opt_count
        opt_upl = options_float_pnl_usdt(opt_snap)
        if opt_upl is not None:
            options_float_pnl_u += opt_upl
            float_pnl_u += opt_upl

    return {
        "trading_day": trading_day,
        "reset_hour": int(reset_hour),
        "open_count": open_count,
        "closed_count": closed_count,
        "win_count": win_count,
        "loss_count": loss_count,
        "win_pnl_u": round(win_pnl_u, 4),
        "loss_pnl_u": round(loss_pnl_u, 4),
        "realized_pnl_u": round(win_pnl_u + loss_pnl_u, 4),
        "open_position_count": open_position_count,
        "options_open_position_count": options_open_position_count,
        "float_pnl_u": round(float_pnl_u, 4),
        "options_float_pnl_u": round(options_float_pnl_u, 4),
    }
