"""关键位程序自动下单开关(三所共用,与 POSITION_SIZING_MODE 联动)."""
from __future__ import annotations

import os
from typing import Any, Optional, Sequence, Tuple

from lib.key_monitor.fib_key_monitor_lib import is_fib_key_monitor_type
from lib.key_monitor.false_breakout_key_monitor_lib import is_false_breakout_key_monitor_type
from lib.key_monitor.key_monitor_full_margin_lib import monitor_type_disallowed_in_full_margin
from lib.key_monitor.key_monitor_lib import KEY_MONITOR_AUTO_TYPES, KEY_MONITOR_RS_TYPES
from lib.key_monitor.trigger_entry_key_monitor_lib import is_trigger_entry_key_monitor_type
from lib.trade.position_sizing_lib import is_full_margin_mode

KEY_ENTRY_REASON_OPTIONS: Tuple[str, ...] = (
    "关键位箱体突破",
    "关键位收敛突破",
    "关键位斐波0.618",
    "关键位斐波0.786",
    "关键位假突破",
    "关键位回调触价开仓",
    "关键位突破触价开仓",
)

KEY_ENTRY_REASON_TRIGGER_OPTIONS: frozenset[str] = frozenset(
    {
        "关键位回调触价开仓",
        "关键位突破触价开仓",
    }
)

KEY_STATS_SEGMENT_KEYS: frozenset[str] = frozenset(
    {
        "key_box",
        "key_conv",
        "key_fib618",
        "key_fib786",
        "key_false_breakout",
        "key_trigger",
    }
)

KEY_STATS_TRIGGER_ONLY: frozenset[str] = frozenset({"key_trigger"})

TREND_MANUAL_ENTRY_REASON_COUNT = 5


def _env_bool(raw: Optional[str], default: bool = False) -> bool:
    if raw is None:
        return default
    return (raw or "").strip().lower() in ("1", "true", "yes", "on")


def load_key_auto_order_enabled(env: Optional[dict] = None) -> bool:
    e = env if env is not None else os.environ
    return _env_bool(e.get("KEY_AUTO_ORDER_ENABLED"), default=False)


def is_key_level_entry_reason(reason: str) -> bool:
    return (reason or "").strip() in KEY_ENTRY_REASON_OPTIONS


def visible_key_entry_reasons(sizing_mode: str, key_auto_enabled: bool) -> Tuple[str, ...]:
    if not key_auto_enabled:
        return ()
    if is_full_margin_mode(sizing_mode):
        return tuple(x for x in KEY_ENTRY_REASON_OPTIONS if x in KEY_ENTRY_REASON_TRIGGER_OPTIONS)
    return KEY_ENTRY_REASON_OPTIONS


def effective_entry_reason_options(
    all_options: Sequence[str],
    sizing_mode: str,
    key_auto_enabled: bool,
    *,
    trend_manual_count: int = TREND_MANUAL_ENTRY_REASON_COUNT,
) -> Tuple[str, ...]:
    """复盘/表单下拉:按开关与计仓模式裁剪关键位开仓类型."""
    opts = list(all_options)
    if len(opts) <= trend_manual_count:
        return tuple(opts)
    key_visible = set(visible_key_entry_reasons(sizing_mode, key_auto_enabled))
    out: list[str] = []
    for i, item in enumerate(opts):
        if i < trend_manual_count:
            out.append(item)
        elif is_key_level_entry_reason(item):
            if item in key_visible:
                out.append(item)
        else:
            out.append(item)
    return tuple(out)


def effective_stats_segment_defs(
    segment_defs: Sequence[Tuple[str, str, Any]],
    sizing_mode: str,
    key_auto_enabled: bool,
) -> Tuple[Tuple[str, str, Any], ...]:
    if not key_auto_enabled:
        hidden = KEY_STATS_SEGMENT_KEYS
    elif is_full_margin_mode(sizing_mode):
        hidden = KEY_STATS_SEGMENT_KEYS - KEY_STATS_TRIGGER_ONLY
    else:
        hidden = frozenset()
    return tuple(x for x in segment_defs if x[0] not in hidden)


def is_key_auto_monitor_type(monitor_type: str) -> bool:
    mt = (monitor_type or "").strip()
    if mt in KEY_MONITOR_AUTO_TYPES:
        return True
    if is_fib_key_monitor_type(mt):
        return True
    if is_false_breakout_key_monitor_type(mt):
        return True
    if is_trigger_entry_key_monitor_type(mt):
        return True
    return False


def is_rs_key_monitor_type(monitor_type: str) -> bool:
    return (monitor_type or "").strip() in KEY_MONITOR_RS_TYPES


def check_monitor_type_add_allowed(
    monitor_type: str,
    sizing_mode: str,
    key_auto_enabled: bool,
) -> Tuple[bool, str]:
    mt = (monitor_type or "").strip()
    if is_rs_key_monitor_type(mt):
        return True, ""
    if not key_auto_enabled:
        return False, (
            "已关闭关键位程序自动单(KEY_AUTO_ORDER_ENABLED=false);"
            "仅可添加「关键支撑阻力」(微信提醒,不下单)."
        )
    if is_full_margin_mode(sizing_mode):
        if monitor_type_disallowed_in_full_margin(mt):
            return False, (
                "全仓杠杆模式下不可添加箱体/收敛突破,斐波或假突破监控;"
                "可使用「回调/突破触价开仓」或关键支撑阻力(仅提醒)."
            )
    if not is_key_auto_monitor_type(mt) and not is_rs_key_monitor_type(mt):
        return False, "监控类型无效"
    return True, ""


def key_auto_order_env_comment_lines() -> Tuple[str, ...]:
    return (
        "# 关键位程序自动下单(与 POSITION_SIZING_MODE 联动,修改后须重启 PM2)",
        "# 默认 false = 关闭所有关键位程序自动单(箱体/收敛/斐波/假突破/触价)",
        "#",
        "#   POSITION_SIZING_MODE=risk(以损定仓)",
        "#     false → 不执行任何关键位自动单;支撑/阻力提醒,人工下单,顺势加仓不受影响",
        "#     true  → 允许关键位全套自动(含触价)",
        "#",
        "#   POSITION_SIZING_MODE=full_margin(全仓杠杆,须无仓切换)",
        "#     false → 不执行触价自动单",
        "#     true  → 仅回调/突破触价可程序自动开仓;箱体/斐波等仍禁止",
        "#",
        "# 顺势加仓,趋势回调不受本开关控制;全仓模式下策略自动仍禁止.",
        "KEY_AUTO_ORDER_ENABLED=false",
    )
