"""中控数据看板:三户当日总览(无 AI,纯数据聚合)."""
from __future__ import annotations

from datetime import datetime, timezone
from typing import Any, Optional

from hub_ai.context import (
    build_daily_context,
    collect_closed_trades_snapshot,
    format_account_remark,
    format_dashboard_account_detail,
)
from hub_ai.config import trading_day_reset_hour
from lib.hub.hub_trades_lib import current_trading_day

LOSS_ALERT_PCT = 5.0
DASHBOARD_POLL_INTERVAL_SEC = 60


def _safe_float(v: Any) -> Optional[float]:
    try:
        if v is None or v == "":
            return None
        return float(v)
    except (TypeError, ValueError):
        return None


def _account_capital_base(ac: dict) -> Optional[float]:
    funding = _safe_float(ac.get("funding_usdt"))
    trading = _safe_float(ac.get("trading_usdt"))
    if funding is not None and trading is not None:
        return funding + trading
    if funding is not None:
        return funding
    if trading is not None:
        return trading
    return None


def _options_layout_enabled(ac: dict) -> bool:
    if str(ac.get("key") or "").lower() != "okx":
        return False
    snap = ac.get("options_snapshot")
    if isinstance(snap, dict) and snap.get("enabled") is not False:
        return True
    return ac.get("options_funding_usdt") is not None or ac.get("options_trading_usdt") is not None


def _perpetual_float_pnl_u(ac: dict) -> Optional[float]:
    try:
        total = float(ac.get("float_pnl_u") or 0)
    except (TypeError, ValueError):
        total = 0.0
    opt = ac.get("options_float_pnl_u")
    if opt is None:
        return round(total, 4)
    try:
        return round(total - float(opt), 4)
    except (TypeError, ValueError):
        return round(total, 4)


def _enrich_account_row(ac: dict) -> dict:
    st = ac.get("trade_stats") or {}
    capital = _account_capital_base(ac)
    day_pnl = float(st.get("total_pnl_u") or 0)
    loss_pct: Optional[float] = None
    loss_alert = False
    if capital is not None and capital > 0 and day_pnl < -1e-9:
        loss_pct = round(abs(day_pnl) / capital * 100.0, 2)
        loss_alert = loss_pct >= LOSS_ALERT_PCT
    return {
        "id": ac.get("id"),
        "key": ac.get("key"),
        "name": ac.get("name"),
        "status": ac.get("status"),
        "monitored": ac.get("status") != "未监控",
        "funding_usdt": ac.get("funding_usdt"),
        "trading_usdt": ac.get("trading_usdt"),
        "perpetual_funding_usdt": ac.get("perpetual_funding_usdt"),
        "perpetual_trading_usdt": ac.get("perpetual_trading_usdt"),
        "options_funding_usdt": ac.get("options_funding_usdt"),
        "options_trading_usdt": ac.get("options_trading_usdt"),
        "options_float_pnl_u": ac.get("options_float_pnl_u"),
        "options_open_position_count": ac.get("options_open_position_count"),
        "options_layout": _options_layout_enabled(ac),
        "perpetual_float_pnl_u": _perpetual_float_pnl_u(ac),
        "capital_total_usdt": round(capital, 4) if capital is not None else None,
        "available_trading_usdt": ac.get("available_trading_usdt"),
        "pnl_u": st.get("total_pnl_u"),
        "closed_count": st.get("closed_count"),
        "win_count": st.get("win_count"),
        "loss_count": st.get("loss_count"),
        "float_pnl_u": ac.get("float_pnl_u"),
        "open_position_count": ac.get("open_position_count"),
        "remark": format_account_remark(ac),
        **format_dashboard_account_detail(ac),
        "issues": ac.get("issues") or [],
        "daily_loss_pct": loss_pct,
        "loss_alert": loss_alert,
    }


def build_dashboard_payload(
    exchanges: list[dict],
    *,
    trading_day: str | None = None,
) -> dict[str, Any]:
    ctx = build_daily_context(exchanges, trading_day=trading_day)
    day = ctx["trading_day"]
    accounts_raw = ctx.get("accounts") or []
    accounts = [
        _enrich_account_row(ac)
        for ac in accounts_raw
        if ac.get("status") != "未监控"
    ]
    closed_trades = collect_closed_trades_snapshot(
        [ac for ac in accounts_raw if ac.get("status") != "未监控"],
        today=day,
    )
    loss_alert_count = sum(1 for ac in accounts if ac.get("loss_alert"))
    now = datetime.now(timezone.utc).astimezone().strftime("%Y-%m-%d %H:%M:%S")
    return {
        "ok": True,
        "updated_at": now,
        "trading_day": day,
        "totals": ctx.get("totals"),
        "accounts": accounts,
        "closed_trades": closed_trades,
        "loss_alert_pct_threshold": LOSS_ALERT_PCT,
        "loss_alert_count": loss_alert_count,
        "poll_interval_sec": DASHBOARD_POLL_INTERVAL_SEC,
    }


def default_trading_day() -> str:
    return current_trading_day(reset_hour=trading_day_reset_hour())
