"""期权持仓监控：浮盈翻倍微信提醒。"""
from __future__ import annotations

import sqlite3
import time
from typing import Any, Callable


def _safe_float(v: Any) -> float | None:
    if v is None:
        return None
    try:
        return float(v)
    except (TypeError, ValueError):
        return None


def build_profit_alert_message(
    *,
    account_label: str,
    inst_id: str,
    premium_paid: float,
    upl: float,
    upl_ratio: float | None,
    bid: float | None,
) -> str:
    pct = f"{upl_ratio * 100:.1f}%" if upl_ratio is not None else "—"
    bid_txt = f"{bid:.4f}" if bid is not None else "—"
    return "\n".join(
        [
            "【OKX期权·翻倍提醒】",
            f"账户：{account_label}",
            f"合约：{inst_id}",
            f"已付权利金：{premium_paid:.4f} USDC",
            f"未实现盈亏：{upl:+.4f} USDC（{pct}）",
            f"当前买一：{bid_txt}（可考虑限价平仓锁利）",
        ]
    )


def run_options_profit_alerts(
    conn: sqlite3.Connection,
    positions: list[dict[str, Any]],
    *,
    profit_ratio: float,
    send_wechat: Callable[[str], None],
    account_label: str,
    ticker_bid_fn: Callable[[str], float | None],
) -> int:
    """
    对比 DB 中 open 记录与交易所持仓；达到阈值发微信。
    返回发送条数。
    """
    sent = 0
    pos_by_inst = {str(p.get("inst_id") or p.get("instId") or ""): p for p in positions}
    rows = conn.execute(
        """
        SELECT id, inst_id, premium_paid, profit_alert_sent
        FROM options_trades
        WHERE status = 'open'
        """
    ).fetchall()
    for row in rows:
        if int(row["profit_alert_sent"] or 0):
            continue
        inst_id = str(row["inst_id"] or "")
        prem = _safe_float(row["premium_paid"])
        if not inst_id or prem is None or prem <= 0:
            continue
        pos = pos_by_inst.get(inst_id)
        if not pos:
            continue
        upl = _safe_float(pos.get("upl"))
        upl_ratio = _safe_float(pos.get("upl_ratio_pct"))
        if upl_ratio is not None:
            ratio = upl_ratio / 100.0
        elif upl is not None:
            ratio = upl / prem
        else:
            continue
        if ratio < float(profit_ratio):
            continue
        bid = ticker_bid_fn(inst_id)
        msg = build_profit_alert_message(
            account_label=account_label,
            inst_id=inst_id,
            premium_paid=prem,
            upl=upl or 0.0,
            upl_ratio=ratio,
            bid=bid,
        )
        try:
            send_wechat(msg)
            conn.execute(
                "UPDATE options_trades SET profit_alert_sent = 1 WHERE id = ?",
                (int(row["id"]),),
            )
            sent += 1
        except Exception:
            pass
    return sent


def options_monitor_loop(
    *,
    enabled: bool,
    poll_seconds: float,
    get_db: Callable[[], sqlite3.Connection],
    fetch_positions: Callable[[], list[dict[str, Any]]],
    ticker_bid_fn: Callable[[str], float | None],
    send_wechat: Callable[[str], None],
    account_label: str,
    profit_ratio: float,
    stop_event: Any = None,
) -> None:
    if not enabled:
        return
    while True:
        if stop_event is not None and getattr(stop_event, "is_set", lambda: False)():
            break
        try:
            conn = get_db()
            try:
                positions = fetch_positions()
                run_options_profit_alerts(
                    conn,
                    positions,
                    profit_ratio=profit_ratio,
                    send_wechat=send_wechat,
                    account_label=account_label,
                    ticker_bid_fn=ticker_bid_fn,
                )
                conn.commit()
            finally:
                conn.close()
        except Exception:
            pass
        time.sleep(max(5.0, float(poll_seconds)))
