"""
交易对分层策略：
- 正常：按原策略处理
- reduced：缩小仓位，并在策略侧提高信号门槛
- blocked：直接禁止自动开仓
"""
import logging
import re
from typing import Any, Dict, Set

logger = logging.getLogger(__name__)


def _parse_symbol_list(raw: Any) -> Set[str]:
    """兼容 string/list/dict 三种配置格式，统一转成大写 symbol 集合。"""
    if raw is None:
        return set()

    if isinstance(raw, dict):
        if "symbols" in raw:
            return _parse_symbol_list(raw.get("symbols"))
        if "items" in raw:
            return _parse_symbol_list(raw.get("items"))
        return set()

    if isinstance(raw, str):
        parts = re.split(r"[\s,;，\n\r\t]+", raw)
        return {p.strip().upper() for p in parts if p and p.strip()}

    if isinstance(raw, list):
        items: Set[str] = set()
        for item in raw:
            if isinstance(item, str):
                sym = item.strip()
            elif isinstance(item, dict):
                sym = str(item.get("symbol") or item.get("value") or "").strip()
            else:
                sym = ""
            if sym:
                items.add(sym.upper())
        return items

    return set()


def _safe_float(value: Any, default: float) -> float:
    try:
        return float(value)
    except (TypeError, ValueError):
        return default


def _safe_int(value: Any, default: int) -> int:
    try:
        return int(value)
    except (TypeError, ValueError):
        return default


def resolve_symbol_trading_policy(symbol: str) -> Dict[str, Any]:
    """
    合并手动名单与统计名单，返回统一的交易对分层结果。

    返回字段：
    - blocked: 是否禁止自动开仓
    - reduced: 是否进入减仓观察名单
    - position_factor: reduced 时建议的仓位系数
    - signal_boost: reduced 时建议提高的最小信号门槛
    - sources: 命中的来源，便于日志定位
    """
    policy = {
        "blocked": False,
        "reduced": False,
        "position_factor": 1.0,
        "signal_boost": 0,
        "sources": [],
    }
    symbol = (symbol or "").strip().upper()
    if not symbol:
        return policy

    try:
        from config_manager import GlobalStrategyConfigManager

        mgr = GlobalStrategyConfigManager()
        stats_symbol = mgr.get("STATS_SYMBOL_FILTERS", {}) or {}

        manual_blocked = _parse_symbol_list(mgr.get("MANUAL_BLOCKED_SYMBOLS", ""))
        manual_reduced = _parse_symbol_list(mgr.get("MANUAL_REDUCED_SYMBOLS", ""))

        manual_position_factor = _safe_float(
            mgr.get("MANUAL_REDUCED_SYMBOL_POSITION_FACTOR", 0.5), 0.5
        )
        manual_position_factor = max(0.05, min(manual_position_factor, 1.0))

        manual_signal_boost = _safe_int(
            mgr.get("MANUAL_REDUCED_SYMBOL_SIGNAL_BOOST", 1), 1
        )
        manual_signal_boost = max(0, min(manual_signal_boost, 5))

        if symbol in manual_blocked:
            policy["blocked"] = True
            policy["sources"].append("manual_blocked")

        if symbol in manual_reduced:
            policy["reduced"] = True
            policy["position_factor"] = min(policy["position_factor"], manual_position_factor)
            policy["signal_boost"] = max(policy["signal_boost"], manual_signal_boost)
            policy["sources"].append("manual_reduced")

        for item in (stats_symbol.get("blacklist") or []):
            if (item.get("symbol") or "").strip().upper() != symbol:
                continue
            mode = (item.get("mode") or "reduced").strip().lower()
            if mode == "hard":
                policy["blocked"] = True
                policy["sources"].append("stats_hard")
            else:
                policy["reduced"] = True
                policy["position_factor"] = min(policy["position_factor"], 0.5)
                policy["signal_boost"] = max(policy["signal_boost"], 1)
                policy["sources"].append("stats_reduced")
            break
    except Exception as e:
        logger.debug(f"{symbol} 读取交易对分层策略失败: {e}")

    if policy["blocked"]:
        policy["reduced"] = False
        policy["position_factor"] = 1.0
        policy["signal_boost"] = 0

    # 去重并保留顺序，便于日志阅读。
    policy["sources"] = list(dict.fromkeys(policy["sources"]))
    return policy
