"""env 配置页 UI 白名单:中文标签,按交易所过滤."""
from __future__ import annotations

import os
from typing import Any, Optional

from lib.env.env_file_lib import env_get_all, read_env_lines
from lib.env.env_schema import (
    _field_type,
    _hot_reload,
    _is_sensitive,
    _mask_value,
    _restart_required,
    parse_env_example_schema,
)

# 各所「交易所与实盘」字段(顺序即页面顺序)
_EXCHANGE_LIVE_FIELDS: dict[str, list[tuple[str, str, str]]] = {
    "okx": [
        ("LIVE_TRADING_ENABLED", "开启实盘下单", "关闭时仅走本地流程,不向交易所发单"),
        ("OKX_API_KEY", "API Key", "永续子账户"),
        ("OKX_API_SECRET", "API Secret", "永续子账户"),
        ("OKX_API_PASSPHRASE", "API Passphrase", "OKX 必填"),
        ("OKX_TD_MODE", "保证金模式", "cross=全仓,isolated=逐仓"),
        ("OKX_POS_MODE", "持仓模式", "hedge=双向,net=单向净持仓"),
        ("OKX_POSITION_INST_TYPE", "仓位查询类型", "如 SWAP"),
        ("OKX_ACCOUNT_LABEL", "账户备注", "企业微信推送中显示"),
    ],
    "binance": [
        ("LIVE_TRADING_ENABLED", "开启实盘下单", "关闭时仅走本地流程,不向交易所发单"),
        ("BINANCE_API_KEY", "API Key", "永续子账户"),
        ("BINANCE_API_SECRET", "API Secret", "永续子账户"),
        ("BINANCE_MARGIN_MODE", "保证金模式", "cross=全仓,isolated=逐仓"),
        ("BINANCE_POSITION_MODE", "持仓模式", "hedge=双向,one_way=单向"),
        ("BINANCE_ACCOUNT_LABEL", "账户备注", "企业微信推送中显示"),
    ],
    "gate": [
        ("LIVE_TRADING_ENABLED", "开启实盘下单", "关闭时仅走本地流程,不向交易所发单"),
        ("GATE_API_KEY", "API Key", "永续子账户"),
        ("GATE_API_SECRET", "API Secret", "永续子账户"),
        ("GATE_TD_MODE", "保证金模式", "cross=全仓,isolated=逐仓"),
        ("GATE_POS_MODE", "持仓模式", "hedge=双向,single=单向"),
        ("GATE_ACCOUNT_LABEL", "账户备注", "企业微信推送中显示"),
    ],
}

_SHARED_SECTIONS: list[dict[str, Any]] = [
    {
        "title": "企业微信",
        "fields": [
            ("WECHAT_WEBHOOK", "机器人 Webhook", "行情与风控推送地址"),
            ("WECHAT_TIMEOUT_SECONDS", "推送超时(秒)", "默认 10"),
        ],
    },
    {
        "title": "交易执行",
        "fields": [
            ("POSITION_SIZING_MODE", "计仓模式", "risk=以损定仓,full_margin=全仓杠杆"),
            ("RISK_PERCENT", "以损定仓风险%", "单笔风险占资金比例"),
            ("FULL_MARGIN_BUFFER_RATIO", "全仓资金缓冲比例", "如 0.98"),
            ("BTC_LEVERAGE", "BTC 默认杠杆", ""),
            ("ALT_LEVERAGE", "山寨默认杠杆", ""),
            ("TRADE_DIRECTION_RESTRICT_ENABLED", "方向限制开关", ""),
            ("TRADE_DIRECTION", "允许方向", "long_only / short_only / both"),
            ("TRADE_SYMBOL_RESTRICT_ENABLED", "币种白名单开关", ""),
            ("TRADE_SYMBOL_WHITELIST", "白名单币种", "逗号分隔,如 BTC,ETH"),
            ("TRADING_DAY_RESET_HOUR", "交易日切点(北京时间)", "整点,默认 8"),
            ("TRADING_DAY_RESET_OPEN_GUARD_ENABLED", "切点前禁止新开仓", ""),
            ("MAX_ACTIVE_POSITIONS", "最大同时持仓", ""),
            ("MANUAL_MIN_PLANNED_RR", "人工最低盈亏比", "如 1.4"),
            ("FORCE_CLOSE_ENABLED", "强制清仓开关", ""),
            ("FORCE_CLOSE_BJ_HOUR", "强制清仓整点(北京)", ""),
        ],
    },
    {
        "title": "交易风控",
        "fields": [
            ("DAILY_OPEN_ALERT_THRESHOLD", "单日开仓提醒阈值", "达次数后 AI 提醒,不拦单"),
            ("DAILY_OPEN_HARD_LIMIT", "单日开仓硬上限", "0=不启用"),
        ],
    },
    {
        "title": "账户冷静期",
        "fields": [
            ("RISK_CONTROL_ENABLED", "冷静期总开关", ""),
            ("RISK_COOLING_HOURS_MANUAL", "手动平仓冷静(小时)", ""),
            ("RISK_COOLING_HOURS_MANUAL_JOURNAL", "复盘情绪冷静(小时)", ""),
            ("RISK_MANUAL_CLOSE_DAILY_LIMIT", "日手动平仓次数上限", ""),
            ("RISK_MOOD_ISSUES_DAILY_FREEZE", "情绪标签日冻结", ""),
        ],
    },
    {
        "title": "自动划转",
        "fields": [
            ("AUTO_TRANSFER_ENABLED", "启用自动划转", ""),
            ("AUTO_TRANSFER_AMOUNT", "目标余额(U)", "交易账户目标 USDT"),
            ("AUTO_TRANSFER_FROM", "划出账户", "funding 或 swap"),
            ("AUTO_TRANSFER_TO", "划入账户", "swap 或 funding"),
            ("AUTO_TRANSFER_BJ_HOUR", "执行整点(北京时间)", ""),
            ("TRANSFER_CCY", "划转币种", "默认 USDT"),
        ],
    },
    {
        "title": "当日资金",
        "fields": [
            ("DAILY_START_CAPITAL", "日起始基数(U)", ""),
            ("DAILY_LOSS_CAPITAL", "回撤后基数(U)", ""),
            ("DAILY_PROFIT_CAPITAL", "盈利后基数(U)", ""),
        ],
    },
]

_OPTIONS_SECTION: dict[str, Any] = {
    "title": "期权账户",
    "exchanges": frozenset({"okx"}),
    "fields": [
        ("OKX_OPTIONS_ENABLED", "启用期权模块", ""),
        ("OKX_OPTIONS_API_KEY", "期权 API Key", "主账户,与永续子账户分离"),
        ("OKX_OPTIONS_API_SECRET", "期权 API Secret", ""),
        ("OKX_OPTIONS_API_PASSPHRASE", "期权 API Passphrase", ""),
        ("OKX_OPTIONS_ACCOUNT_LABEL", "期权账户备注", ""),
        ("OKX_OPTIONS_TRADE_BUDGET_USDC", "单笔预算(USDC)", ""),
        ("OKX_OPTIONS_BUDGET_BUFFER", "预算缓冲比例", "如 0.95"),
        ("OKX_OPTIONS_DEFAULT_UNDERLY", "默认标的", "如 ETH"),
    ],
}

_HEDGE_PLAN_SECTION: dict[str, Any] = {
    "title": "对冲计划",
    "exchanges": frozenset({"okx"}),
    "fields": [
        ("HEDGE_PLAN_ENABLED", "启用对冲计划", "关闭则隐藏导航且不可开仓"),
        ("HEDGE_PLAN_LIVE_ORDER", "允许对冲真实下单", "再与实盘 LIVE_TRADING_ENABLED 同开才可启动永期"),
        ("HEDGE_PLAN_OPEN_ORDER", "永期开仓顺序", "options_first 或 perp_first"),
        ("HEDGE_PLAN_ON_PERP_SL_CLOSE_OPTIONS", "永期止损后强制平期权", "保护机制,建议保持 true"),
        ("HEDGE_PLAN_ON_PERP_TP_CLOSE_OPTIONS", "永期止盈后强制平期权", "默认 false,保险腿不平"),
        ("HEDGE_PLAN_OO_CLOSE_WINNER_ONLY", "期期只平盈利腿", "达目标价只平盈利方"),
        ("MAX_ACTIVE_HEDGE_PLANS", "最大同时活跃计划数", "建议 1"),
        ("HEDGE_PLAN_MONITOR_POLL_SECONDS", "对冲监控轮询(秒)", "默认 15"),
        ("HEDGE_PLAN_PARTIAL_AUTO_CLOSE_OPTION", "半腿失败时自动平期权", ""),
    ],
}


# 与运行时 os.getenv 默认一致;.env 未写明时展示实际生效值(同风控说明页)
_RUNTIME_ENV_DEFAULTS: dict[str, str] = {
    "RISK_CONTROL_ENABLED": "true",
    "RISK_COOLING_HOURS_MANUAL": "4",
    "RISK_COOLING_HOURS_MANUAL_JOURNAL": "1",
    "RISK_MANUAL_CLOSE_DAILY_LIMIT": "2",
    "RISK_MOOD_ISSUES_DAILY_FREEZE": "true",
}


def _effective_env_value(key: str, file_values: dict[str, str], schema_default: str = "") -> str:
    if key in file_values:
        return file_values[key]
    runtime = os.getenv(key)
    if runtime is not None and str(runtime).strip() != "":
        return str(runtime).strip()
    if schema_default:
        return schema_default
    return _RUNTIME_ENV_DEFAULTS.get(key, "")


def _schema_field_map(example_path: str) -> dict[str, dict[str, Any]]:
    out: dict[str, dict[str, Any]] = {}
    for group in parse_env_example_schema(example_path):
        for field in group.get("fields") or []:
            out[field["key"]] = dict(field)
    return out


def _build_field(
    key: str,
    label: str,
    note: str,
    schema: dict[str, dict[str, Any]],
    values: dict[str, str],
) -> dict[str, Any]:
    meta = schema.get(key) or {}
    schema_default = meta.get("default") or ""
    val = _effective_env_value(key, values, schema_default)
    masked = _mask_value(key, val)
    ftype = meta.get("type") or _field_type(key, val or schema_default)
    return {
        "key": key,
        "label": label,
        "note": note or meta.get("note") or "",
        "default": val,
        "type": ftype,
        "sensitive": meta.get("sensitive", _is_sensitive(key)),
        "restart_required": meta.get("restart_required", _restart_required(key)),
        "hot_reload": meta.get("hot_reload", _hot_reload(key)),
        "current": masked["value"] if not _is_sensitive(key) else "",
        "masked": masked["masked"],
        "tail": masked.get("tail") or "",
        "has_value": masked["has_value"],
    }


def ui_sections_for_exchange(exchange_key: str) -> list[dict[str, Any]]:
    ex = (exchange_key or "").strip().lower()
    sections: list[dict[str, Any]] = []
    live_fields = _EXCHANGE_LIVE_FIELDS.get(ex, _EXCHANGE_LIVE_FIELDS["okx"])
    sections.append({"title": "交易所与实盘", "fields": live_fields})
    sections.extend(_SHARED_SECTIONS)
    if ex in _OPTIONS_SECTION.get("exchanges", frozenset()):
        sections.append(_OPTIONS_SECTION)
    if ex in _HEDGE_PLAN_SECTION.get("exchanges", frozenset()):
        sections.append(_HEDGE_PLAN_SECTION)
    return sections


def ui_allowed_keys(exchange_key: str) -> frozenset[str]:
    keys: set[str] = set()
    for sec in ui_sections_for_exchange(exchange_key):
        for item in sec["fields"]:
            keys.add(item[0])
    return frozenset(keys)


def build_exchange_api_group(
    exchange_key: str,
    example_path: str,
    env_path: str,
) -> dict[str, Any]:
    """系统设置「交易所 API」专用:仅交易所与实盘字段."""
    schema = _schema_field_map(example_path)
    values = env_get_all(read_env_lines(env_path))
    ex = (exchange_key or "").strip().lower()
    live_fields = _EXCHANGE_LIVE_FIELDS.get(ex, _EXCHANGE_LIVE_FIELDS["okx"])
    fields = [
        _build_field(key, label, note, schema, values)
        for key, label, note in live_fields
    ]
    return {
        "title": "交易所 API",
        "fields": fields,
        "has_restart": any(f.get("restart_required") for f in fields),
    }


def build_env_ui_payload(
    exchange_key: str,
    example_path: str,
    env_path: str,
) -> list[dict[str, Any]]:
    schema = _schema_field_map(example_path)
    env_lines = read_env_lines(env_path)
    values = env_get_all(env_lines)
    groups: list[dict[str, Any]] = []
    for sec in ui_sections_for_exchange(exchange_key):
        fields = [
            _build_field(key, label, note, schema, values)
            for key, label, note in sec["fields"]
        ]
        groups.append({
            "title": sec["title"],
            "fields": fields,
            "has_restart": any(f.get("restart_required") for f in fields),
        })
    return groups


def filter_updates_for_ui(exchange_key: str, updates: dict[str, str]) -> dict[str, str]:
    allowed = ui_allowed_keys(exchange_key)
    return {k: v for k, v in (updates or {}).items() if k in allowed}


def validate_env_ui_updates(
    exchange_key: str,
    example_path: str,
    updates: dict[str, str],
) -> tuple[dict[str, str], list[str]]:
    from lib.env.env_schema import validate_env_updates

    schema = _schema_field_map(example_path)
    groups: list[dict[str, Any]] = []
    for sec in ui_sections_for_exchange(exchange_key):
        fields: list[dict[str, Any]] = []
        for key, _label, _note in sec["fields"]:
            if key in schema:
                fields.append(schema[key])
            else:
                default = ""
                fields.append(
                    {
                        "key": key,
                        "type": _field_type(key, default),
                        "sensitive": _is_sensitive(key),
                        "restart_required": _restart_required(key),
                        "hot_reload": _hot_reload(key),
                    }
                )
        groups.append({"title": sec["title"], "fields": fields})
    return validate_env_updates(groups, updates)
