"""对冲计划企业微信推送(起止必发,幂等落库标记)."""
from __future__ import annotations

from typing import Any, Callable, Optional

from lib.hedge_plan.hedge_plan_db import update_plan


def _fmt(v: Any, d: int = 2) -> str:
    try:
        if v is None or v == "":
            return "—"
        return f"{float(v):.{d}f}"
    except (TypeError, ValueError):
        return str(v)


def _type_label(plan_type: str) -> str:
    return "永期对冲" if (plan_type or "") == "perp_options" else "期期对冲"


def _dir_label(direction: str) -> str:
    d = (direction or "").lower()
    if d == "long":
        return "做多"
    if d == "short":
        return "做空"
    return "—"


def build_hedge_start_message(plan: dict[str, Any], *, legs: Optional[list[dict[str, Any]]] = None) -> str:
    pt = plan.get("plan_type") or ""
    lines = [
        f"🟢 对冲计划启动 #{plan.get('id')}",
        f"📌 类型:{_type_label(pt)}",
        f"🪙 标的:{plan.get('underlying') or '—'}",
    ]
    if pt == "perp_options":
        lines.extend(
            [
                f"📈 方向:{_dir_label(plan.get('direction') or '')}",
                f"💵 开仓参考:{_fmt(plan.get('entry_mark'))}",
                f"🎯 止盈:{_fmt(plan.get('tp'))}｜止损:{_fmt(plan.get('sl'))}",
                f"📦 永续张数:{_fmt(plan.get('perp_size'), 4)}｜杠杆:{_fmt(plan.get('leverage'), 0)}x",
                f"💎 期权保费合计:{_fmt(plan.get('premium_total'), 4)} USDC",
            ]
        )
    else:
        lines.extend(
            [
                f"🎯 上破:{_fmt(plan.get('target_price_up') or plan.get('target_price'))}"
                f"｜下破:{_fmt(plan.get('target_price_down') or plan.get('target_price'))}",
                f"💎 期权保费合计:{_fmt(plan.get('premium_total'), 4)} USDC",
            ]
        )
    if legs:
        for leg in legs:
            role = leg.get("leg_role") or ""
            if role == "perp":
                lines.append(f"· 永续腿 {leg.get('symbol') or ''} ×{_fmt(leg.get('size'), 4)}")
            else:
                lines.append(
                    f"· {role} {(leg.get('opt_type') or '')} K{_fmt(leg.get('strike'), 0)} "
                    f"×{_fmt(leg.get('size'), 0)}张 {leg.get('inst_id') or ''}"
                )
    lines.append("📎 独立模块推送,不进普通交易复盘")
    return "\n".join(lines)


def build_hedge_end_message(plan: dict[str, Any]) -> str:
    reason = plan.get("close_reason") or "—"
    total = plan.get("realized_pnl_total")
    try:
        tv = float(total) if total is not None else None
    except (TypeError, ValueError):
        tv = None
    head = "🔴" if (tv is not None and tv < 0) else "🟢"
    reason_map = {
        "perp_tp": "永续止盈(期权默认不平)",
        "perp_sl": "永续止损(期权强制平)",
        "target_win_leg": "期期已平盈利腿(中间态)",
        "target_up_win_leg": "期期上破·已平盈利腿",
        "target_down_win_leg": "期期下破·已平盈利腿",
        "oo_expiry_loss": "期期到期无盈利·总亏损",
        "oo_expiry_win": "期期到期仍盈利",
        "expiry": "到期收口",
        "manual": "人工结束",
        "partial_fail": "半腿失败收尾",
        "cancelled": "已取消",
    }
    lines = [
        f"{head} 对冲计划结束 #{plan.get('id')}",
        f"📌 类型:{_type_label(plan.get('plan_type') or '')}",
        f"🪙 标的:{plan.get('underlying') or '—'}",
        f"📎 原因:{reason_map.get(reason, reason)}",
        f"💰 合计≈U:{_fmt(total)}",
        f"· 永续分项:{_fmt(plan.get('realized_pnl_perp'))} USDT",
        f"· 期权分项:{_fmt(plan.get('realized_pnl_options'))} USDC(≈U 1:1)",
        f"⏱ 开仓:{plan.get('opened_at') or '—'}｜结束:{plan.get('closed_at') or '—'}",
    ]
    return "\n".join(lines)


def build_hedge_alert_message(
    *,
    title: str,
    plan_id: Any = None,
    detail: str = "",
) -> str:
    lines = [f"⚠️ 对冲计划告警{(' #' + str(plan_id)) if plan_id else ''}", f"📌 {title}"]
    if detail:
        lines.append(str(detail)[:800])
    return "\n".join(lines)


def notify_hedge(
    cfg: dict[str, Any],
    content: str,
) -> bool:
    send: Optional[Callable[[str], Any]] = cfg.get("send_wechat")
    if not callable(send):
        return False
    try:
        send(content)
        return True
    except Exception:
        return False


def notify_plan_start(
    cfg: dict[str, Any],
    conn: Any,
    plan: dict[str, Any],
    legs: Optional[list[dict[str, Any]]] = None,
) -> bool:
    if int(plan.get("wechat_start_sent") or 0):
        return False
    ok = notify_hedge(cfg, build_hedge_start_message(plan, legs=legs))
    if ok and plan.get("id") is not None:
        update_plan(conn, int(plan["id"]), wechat_start_sent=1)
        plan["wechat_start_sent"] = 1
    return ok


def notify_plan_end(cfg: dict[str, Any], conn: Any, plan: dict[str, Any]) -> bool:
    if int(plan.get("wechat_end_sent") or 0):
        return False
    # 中间态 target_win_leg 不算正式结束推送(用告警)
    if (plan.get("close_reason") or "") in (
        "target_win_leg",
        "target_up_win_leg",
        "target_down_win_leg",
    ) and (plan.get("status") or "") != "closed":
        side = "上破" if "up" in str(plan.get("close_reason")) else (
            "下破" if "down" in str(plan.get("close_reason")) else "目标价"
        )
        notify_hedge(
            cfg,
            build_hedge_alert_message(
                title=f"期期{side}已平盈利腿,亏损腿继续持有至到期",
                plan_id=plan.get("id"),
                detail=(
                    f"上破 {_fmt(plan.get('target_price_up') or plan.get('target_price'))}"
                    f"｜下破 {_fmt(plan.get('target_price_down') or plan.get('target_price'))}"
                ),
            ),
        )
        return True
    ok = notify_hedge(cfg, build_hedge_end_message(plan))
    if ok and plan.get("id") is not None:
        update_plan(conn, int(plan["id"]), wechat_end_sent=1)
        plan["wechat_end_sent"] = 1
    return ok


def notify_partial_fail(cfg: dict[str, Any], *, plan_type: str, msg: str, results: Any = None) -> bool:
    detail = msg
    if results:
        try:
            detail = f"{msg}\n路径结果:{results}"[:800]
        except Exception:
            pass
    return notify_hedge(
        cfg,
        build_hedge_alert_message(title=f"{_type_label(plan_type)}半腿失败", detail=detail),
    )
