"""LIVE 组净盈亏：交易所永续 UPL/资金费 + 本地期权净盈亏 − 真实手续费。"""

from __future__ import annotations

import logging
import time
from typing import Any, Protocol

logger = logging.getLogger(__name__)


class _FeeFundingClient(Protocol):
    def get_perp_upl_usdt(self, *args: Any, **kwargs: Any) -> float | None: ...

    def get_funding_usdt(self, *args: Any, **kwargs: Any) -> float: ...

    def get_closed_perp_pnl_usdt(self, *args: Any, **kwargs: Any) -> float | None: ...


def group_paid_fees_usdt(db: Any, group_id: str) -> float:
    rows = db.fetchall(
        "SELECT fee FROM fills WHERE group_id=?",
        (group_id,),
    )
    return sum(abs(float(r["fee"] or 0)) for r in rows)


def enrich_live_unrealized(
    *,
    base: dict[str, Any],
    db: Any,
    client: Any,
    exchange: str,
    perp_inst_id: str,
    perp_side: str,
    open_at_ms: int | None,
) -> dict[str, Any]:
    """
    在 Matcher.unrealized 结果上覆盖 LIVE 口径：
    net = 永续交易所UPL + 期权净盈亏(本地) − 入场手续费×2 + 资金费(signed)
    离场手续费按入场手续费估算（开+平 ≈ 已付×2）。
    """
    if not base.get("has_position"):
        return base
    group_id = str(base.get("group_id") or "")
    fees_paid = group_paid_fees_usdt(db, group_id) if group_id else 0.0

    begin = int(open_at_ms or 0)
    funding = 0.0
    perp_upl = float(base.get("perp_upl") or 0.0)
    ex = (exchange or "").lower()

    try:
        if ex == "binance":
            side = "LONG" if perp_side == "long" else "SHORT"
            upl = client.get_perp_upl_usdt(perp_inst_id, position_side=side)
            if upl is not None:
                perp_upl = float(upl)
            if begin > 0:
                funding = float(
                    client.get_funding_usdt(perp_inst_id, begin_ms=begin) or 0.0
                )
        else:
            upl = client.get_perp_upl_usdt(perp_inst_id, pos_side=perp_side)
            if upl is not None:
                perp_upl = float(upl)
            if begin > 0:
                funding = float(
                    client.get_funding_usdt(perp_inst_id, begin_ms=begin) or 0.0
                )
    except Exception as e:
        logger.warning("live unrealized exchange overlay failed: %s", e)

    option_upl = float(base.get("option_upl") or 0.0)  # 期权净盈亏（本地）
    # 盯盘/达标：离场费 ≈ 入场费 → 合计扣 已付×2
    est_close = float(fees_paid)
    net_pnl = perp_upl + option_upl - fees_paid * 2.0 + funding

    out = dict(base)
    out["perp_upl"] = perp_upl
    out["option_upl"] = option_upl
    out["fees_paid"] = fees_paid
    out["funding_usdt"] = funding
    out["est_close_fees"] = est_close
    out["net_pnl"] = net_pnl
    out["pnl_source"] = "live_exchange"
    return out


def reconcile_closed_group_pnl(
    *,
    db: Any,
    client: Any,
    exchange: str,
    group_id: str,
    perp_inst_id: str,
    open_at_ms: int | None,
    local_net: float | None,
) -> float:
    """
    平仓后回写：净盈亏优先用 交易所永续已实现 + 本地期权腿盈亏 − 手续费 + 资金费。
    失败则退回 local_net。
    """
    from ..sim.pnl import summarize_fills_pnl

    fills = db.fetchall(
        "SELECT * FROM fills WHERE group_id=? ORDER BY id ASC", (group_id,)
    )
    summary = summarize_fills_pnl(list(fills))
    fees = float(summary.get("fees_total") or 0.0)
    option_pnl = summary.get("option_pnl")
    local_perp = summary.get("perp_pnl")

    begin = int(open_at_ms or 0)
    end = int(time.time() * 1000)
    funding = 0.0
    exch_perp: float | None = None
    ex = (exchange or "").lower()
    try:
        if begin > 0:
            funding = float(client.get_funding_usdt(perp_inst_id, begin_ms=begin, end_ms=end) or 0.0)
        exch_perp = client.get_closed_perp_pnl_usdt(
            perp_inst_id, begin_ms=begin, end_ms=end
        )
    except Exception as e:
        logger.warning("reconcile exchange pnl failed: %s", e)

    perp_pnl = float(exch_perp) if exch_perp is not None else (
        float(local_perp) if local_perp is not None else 0.0
    )
    opt = float(option_pnl) if option_pnl is not None else 0.0
    net = perp_pnl + opt - fees + funding

    if local_net is not None and exch_perp is None and abs(funding) < 1e-12:
        # 交易所永续已实现拉不到且无资金费 → 保持本地
        net = float(local_net)

    with db._lock:
        try:
            db._conn.execute(
                "UPDATE groups SET realized_pnl=?, funding_usdt=?, fees=? WHERE group_id=?",
                (float(net), float(funding), float(fees), group_id),
            )
            db._conn.commit()
        except Exception:
            # funding_usdt 列未迁移时降级
            db._conn.execute(
                "UPDATE groups SET realized_pnl=?, fees=? WHERE group_id=?",
                (float(net), float(fees), group_id),
            )
            db._conn.commit()
    return float(net)
