#!/usr/bin/env python3
"""
kis_trader/backtest/param_search_cli_common.py — 포트폴리오 파라서치 공통 CLI
=============================================================================
꼬리·스캘핑·모멘텀·돌파는 동일한 run 옵션 패턴을 쓴다 (하락매수 UPDOW 제외).

예시 (전략 파일만 바꿈):
    python3 kis_trader/backtest/param_search_momentum.py \\
      --start 2026-05-01 --end 2026-05-31 \\
      --slot-money 200000 --max-stocks 20 --total-budget 2000000 \\
      --time-start 830 --time-end 1530 \\
      --mode fast
"""
from __future__ import annotations

import argparse
from typing import Any, Dict, Optional

# 파라서치 공통 필터 기본값 (정렬은 각 스크립트 total_pnl 유지)
MIN_WIN_RATE_DEFAULT = 40.0
MIN_PF_DEFAULT = 1.0


def combo_passes_search_filters(
    *,
    win_rate: float,
    pf: float,
    min_win_rate: float,
    min_pf: float,
) -> bool:
    """승률·PF 하한 — 워커·머지 단계 공통."""
    if float(win_rate) < float(min_win_rate):
        return False
    if float(pf) < float(min_pf):
        return False
    return True


def add_search_filter_cli_args(parser: argparse.ArgumentParser) -> None:
    """승률·PF 하한 CLI (--min_win_rate, --min_pf)."""
    parser.add_argument(
        "--min_win_rate",
        default=MIN_WIN_RATE_DEFAULT,
        type=float,
        help="승률 하한(%%). 기본 40",
    )
    parser.add_argument(
        "--min_pf",
        default=MIN_PF_DEFAULT,
        type=float,
        help="Profit Factor 하한 (총익/|총손|). 기본 1.0",
    )


def add_portfolio_cli_args(parser: argparse.ArgumentParser) -> None:
    """1회투자·동시보유·총한도·매매시간 — tail/scalp/momentum/breakout 공통."""
    parser.add_argument(
        "--time-start", type=int, default=None, dest="time_start",
        help="매수 시작 HHMM (미지정 시 DB·전략 기본값)",
    )
    parser.add_argument(
        "--time-end", type=int, default=None, dest="time_end",
        help="매수 종료 HHMM (미지정 시 DB·전략 기본값)",
    )
    parser.add_argument(
        "--slot-money", type=float, default=None, dest="slot_money",
        help="1회투자금(원). 미지정 시 DB 전략별 SLOT_*",
    )
    parser.add_argument(
        "--max-stocks", type=int, default=None, dest="max_stocks",
        help="동시보유 종목 수. 미지정 시 DB 전략 MAX_*_STOCKS",
    )
    parser.add_argument(
        "--total-budget", type=float, default=None, dest="total_budget",
        help="총 운용한도(원). 0/미지정 시 동시×1회투자",
    )


def apply_session_to_fixed(
    fixed: Dict[str, Any],
    *,
    time_start_hm: Optional[int] = None,
    time_end_hm: Optional[int] = None,
) -> None:
    """CLI 매매시간 → 백테 base fixed dict (in-place)."""
    if time_start_hm is not None:
        fixed["time_start_hm"] = int(time_start_hm)
    if time_end_hm is not None:
        fixed["time_end_hm"] = int(time_end_hm)


def search_json_meta(
    portfolio: Dict[str, Any],
    fixed: Dict[str, Any],
) -> Dict[str, Any]:
    """JSON 저장·--apply meta — 포트폴리오 + 매매시간."""
    return {
        "slot_money": portfolio.get("slot_money"),
        "max_stocks": portfolio.get("max_stocks"),
        "total_budget_krw": portfolio.get("total_budget_krw"),
        "time_start_hm": fixed.get("time_start_hm"),
        "time_end_hm": fixed.get("time_end_hm"),
        "portfolio": dict(portfolio),
    }


def format_session_hm(fixed: Dict[str, Any]) -> str:
    ts = int(fixed.get("time_start_hm") or 930)
    te = int(fixed.get("time_end_hm") or 1530)
    return f"{ts:04d}-{te:04d}"
