"""对冲计划与单独期权开仓互斥门控.

默认开启:有进行中对冲计划时禁止单独开期权;有纯期权持仓时禁止启动对冲计划.
关闭 HEDGE_PLAN_OPTIONS_MUTUAL_EXCLUSIVE 后两边可同时开.
"""
from __future__ import annotations

import os
from typing import Any, Callable, Optional


def _env_bool(key: str, default: bool = False) -> bool:
    v = (os.getenv(key) or "").strip().lower()
    if not v:
        return default
    return v in ("1", "true", "yes", "on")


def mutual_exclusive_enabled() -> bool:
    return _env_bool("HEDGE_PLAN_OPTIONS_MUTUAL_EXCLUSIVE", True)


def block_standalone_option_open_msg(conn: Any) -> Optional[str]:
    """若应拦截单独开期权,返回中文原因;否则 None."""
    if not mutual_exclusive_enabled():
        return None
    try:
        from lib.hedge_plan.hedge_plan_db import count_active_plans, init_hedge_plan_tables

        init_hedge_plan_tables(conn)
        if count_active_plans(conn) > 0:
            return "存在进行中对冲计划,禁止单独开期权(可在 env「对冲与期权互斥门控」关闭)"
    except Exception:
        return "互斥门控校验失败,暂禁止单独开期权"
    return None


def _pos_nonzero(raw: dict[str, Any]) -> bool:
    try:
        return abs(float(raw.get("pos") or 0)) > 1e-12
    except (TypeError, ValueError):
        return False


def has_standalone_option_position(conn: Any, raw_positions: list[dict[str, Any]] | None) -> bool:
    """交易所期权持仓中,是否存在未挂在进行中对冲计划腿上的仓位."""
    if not raw_positions:
        return False
    from lib.instance.instance_dashboard_lib import _resolve_options_source

    for p in raw_positions:
        if not isinstance(p, dict) or not _pos_nonzero(p):
            continue
        inst = str(p.get("instId") or p.get("inst_id") or "").strip()
        if not inst:
            continue
        source, _, _ = _resolve_options_source(conn, inst)
        if source == "option":
            return True
    return False


def block_hedge_plan_start_msg(
    conn: Any,
    *,
    fetch_positions: Optional[Callable[[Any], Any]] = None,
    exchange: Any = None,
    raw_positions: list[dict[str, Any]] | None = None,
) -> Optional[str]:
    """若应拦截启动对冲计划,返回中文原因;否则 None."""
    if not mutual_exclusive_enabled():
        return None
    rows = raw_positions
    if rows is None:
        if fetch_positions is None or exchange is None:
            return None
        try:
            rows = fetch_positions(exchange) or []
        except Exception:
            return "获取期权持仓失败,暂禁止启动对冲计划"
    try:
        if has_standalone_option_position(conn, rows):
            return "存在单独期权持仓,禁止启动对冲计划(可在 env「对冲与期权互斥门控」关闭)"
    except Exception:
        return "互斥门控校验失败,暂禁止启动对冲计划"
    return None
