#!/usr/bin/env python3
"""
kis_trader/backtest/param_search_dart.py — DART Optuna/Grid 축
"""
from __future__ import annotations

from typing import Any, Dict, List

from database import TradeDB
from kis_trader.backtest.dart_backtest_common import run_dart_backtest_web_aligned
from kis_trader.engine import dart_engine as de
from kis_trader.utils.env import get_env_bool


def _dart_grids() -> Dict[str, Dict[str, List[Any]]]:
    """mode → 축. 실매 기본값이 각 축에 포함."""
    d = de.get_dart_defaults_from_db()
    rsi_os = float(d.get("rsi_oversold", 30))
    rsi_rc = float(d.get("rsi_reclaim", 35))
    sl = float(d.get("sl_pct", 0.02))
    tp = float(d.get("tp_pct", 0.04))
    vol = float(d.get("vol_mult", 1.5))
    win = int(d.get("event_window_bars", 120))
    return {
        "fast": {
            "rsi_oversold": sorted({rsi_os, 25.0, 30.0, 35.0}),
            "rsi_reclaim": sorted({rsi_rc, 32.0, 35.0, 40.0}),
            "sl_pct": sorted({sl, 0.015, 0.02, 0.025}),
            "tp_pct": sorted({tp, 0.03, 0.04, 0.05}),
            "vol_mult": sorted({vol, 1.2, 1.5, 2.0}),
            "event_window_bars": sorted({win, 60, 120, 180}),
        },
        "coarse": {
            "rsi_oversold": [20.0, 25.0, 30.0, 35.0],
            "rsi_reclaim": [30.0, 35.0, 40.0, 45.0],
            "sl_pct": [0.015, 0.02, 0.03],
            "tp_pct": [0.03, 0.04, 0.06],
            "vol_mult": [1.0, 1.5, 2.0, 2.5],
            "event_window_bars": [60, 90, 120, 180],
            "trail_pct": [0.01, 0.015, 0.02],
            "trail_arm_pct": [0.015, 0.02, 0.03],
        },
        "fine": {
            "rsi_oversold": sorted({rsi_os, rsi_os - 2, rsi_os + 2, 28.0, 30.0}),
            "rsi_reclaim": sorted({rsi_rc, rsi_rc - 2, rsi_rc + 2, 35.0, 38.0}),
            "sl_pct": sorted({sl, 0.018, 0.02, 0.022}),
            "tp_pct": sorted({tp, 0.035, 0.04, 0.045}),
            "vol_mult": sorted({vol, 1.3, 1.5, 1.8}),
            "event_window_bars": sorted({win, 90, 120, 150}),
        },
    }


def apply_params_to_db(params: Dict[str, Any]) -> None:
    """Optuna --apply-best 전용. 포트폴리오 키 제외."""
    if not get_env_bool("DART_TRADE_ENABLED", False):
        # 적용은 허용하되 매매 스위치는 사용자 것 유지
        pass
    mapping = {
        "rsi_oversold": "DART_RSI_OVERSOLD",
        "rsi_reclaim": "DART_RSI_RECLAIM",
        "sl_pct": "DART_STOP_LOSS_PCT",
        "tp_pct": "DART_TAKE_PROFIT_PCT",
        "vol_mult": "DART_VOL_MULT",
        "event_window_bars": "DART_EVENT_WINDOW_BARS",
        "trail_pct": "DART_TRAIL_PCT",
        "trail_arm_pct": "DART_TRAIL_ARM_PCT",
        "rsi_period": "DART_RSI_PERIOD",
        "max_hold_bars": "DART_MAX_HOLD_BARS",
    }
    patch = {}
    for k, env_k in mapping.items():
        if k in params:
            patch[env_k] = str(params[k])
    if not patch:
        return
    db = TradeDB()
    try:
        db.insert_env_snapshot(patch)
    finally:
        db.close()


def evaluate_dart_param_combo(
    params: Dict[str, Any],
    *,
    start: str,
    end: str,
    env_row: Dict[str, Any],
) -> Dict[str, Any]:
    base = de.get_dart_defaults_from_db(env_row=env_row)
    base.update(params)
    return run_dart_backtest_web_aligned(
        start=start, end=end, params=base, env_row=env_row,
    )
