#!/usr/bin/env python3
"""
kis_trader/backtest/optuna_common.py — Optuna storage·DB 공통 (MariaDB 141)
=========================================================================
TradeDB(database.py) 와 동일 호스트·계정, 전용 DB kis_optuna 에 study 저장.
Win11·VM 양쪽에서 같은 storage 로 trial 공유·재개 가능.
"""
from __future__ import annotations

import logging
import os
from typing import Optional
from urllib.parse import quote_plus

from kis_trader.utils.env import get_env_from_db

logger = logging.getLogger("optuna_common")

# Optuna 전용 MariaDB (매매 DB kis_quant_db 와 분리)
DEFAULT_OPTUNA_DB_NAME = "kis_optuna"
OPTUNA_STRATEGIES = ("tail", "momentum", "breakout")


def mariadb_creds() -> dict:
    """TradeDB(database.py) 와 동일 우선순위 — env > 기본 141."""
    return {
        "host": os.environ.get("DB_HOST", "192.168.0.141"),
        "port": int(os.environ.get("DB_PORT", "3306")),
        "user": os.environ.get("DB_USER", "jae"),
        "password": os.environ.get("DB_PASS", "1234"),
    }


def resolve_optuna_db_name() -> str:
    """
    Optuna storage DB — 기본 kis_optuna (매매 kis_quant_db 와 분리).
    env OPTUNA_DB_NAME 로 오버라이드 가능.
    """
    raw = get_env_from_db("OPTUNA_DB_NAME", "")
    if raw and str(raw).strip() not in ("", "None"):
        return str(raw).strip()
    env = os.environ.get("OPTUNA_DB_NAME", "")
    if env and str(env).strip():
        return str(env).strip()
    return DEFAULT_OPTUNA_DB_NAME


def build_mariadb_storage_url(db_name: Optional[str] = None) -> str:
    """mysql+pymysql://…@141/optuna 형식 storage URL."""
    creds = mariadb_creds()
    name = (db_name or resolve_optuna_db_name()).strip()
    user = quote_plus(creds["user"])
    passwd = quote_plus(creds["password"])
    return (
        f"mysql+pymysql://{user}:{passwd}@{creds['host']}:{creds['port']}/{name}"
        f"?charset=utf8mb4"
    )


def ensure_optuna_database(db_name: Optional[str] = None) -> str:
    """
    MariaDB 141 — kis_optuna 존재 확인 (없으면 CREATE 시도).
    """
    name = (db_name or resolve_optuna_db_name()).strip()
    creds = mariadb_creds()

    try:
        import pymysql
    except ImportError as exc:
        raise ImportError(
            "Optuna MariaDB storage 는 pymysql 필요: pip install PyMySQL"
        ) from exc

    # DB 존재 여부만 확인 (이미 있으면 CREATE 생략)
    conn = pymysql.connect(
        host=creds["host"],
        port=creds["port"],
        user=creds["user"],
        password=creds["password"],
        charset="utf8mb4",
        autocommit=True,
        connect_timeout=10,
    )
    try:
        with conn.cursor() as cur:
            cur.execute("SHOW DATABASES LIKE %s", (name,))
            exists = cur.fetchone() is not None
            if not exists:
                cur.execute(
                    f"CREATE DATABASE IF NOT EXISTS `{name}` "
                    "DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"
                )
                logger.info(
                    "📦 Optuna DB 생성: %s@%s:%s/%s",
                    creds["user"], creds["host"], creds["port"], name,
                )
            else:
                logger.info(
                    "📦 Optuna storage DB: %s@%s:%s/%s",
                    creds["user"], creds["host"], creds["port"], name,
                )
    except Exception as exc:
        logger.error("❌ Optuna DB '%s' 접속/확인 실패: %s", name, exc)
        raise
    finally:
        conn.close()
    return name


def resolve_optuna_storage_url(cli_override: Optional[str] = None) -> str:
    """
    Storage URL 우선순위:
      1) CLI --storage
      2) OPTUNA_STORAGE_URL (DB/env)
      3) MariaDB 141 / kis_optuna (TradeDB 동일 계정)
    """
    if cli_override and str(cli_override).strip():
        return str(cli_override).strip()
    from_db = get_env_from_db("OPTUNA_STORAGE_URL", "")
    if from_db and str(from_db).strip() not in ("", "None"):
        return str(from_db).strip()
    db_name = ensure_optuna_database()
    return build_mariadb_storage_url(db_name)


def resolve_study_name(
    *,
    strategy: str,
    mode: str,
    start: str,
    end: str,
    cli_override: Optional[str] = None,
) -> str:
    """Study 이름 — 전략·기간·모드 포함."""
    if cli_override and str(cli_override).strip():
        return str(cli_override).strip()
    env_key = f"OPTUNA_{strategy.upper()}_STUDY_NAME"
    from_db = get_env_from_db(env_key, "")
    if from_db and str(from_db).strip() not in ("", "None"):
        return str(from_db).strip()
    legacy = get_env_from_db("OPTUNA_TAIL_STUDY_NAME", "")
    if strategy == "tail" and legacy and str(legacy).strip() not in ("", "None"):
        return str(legacy).strip()
    return f"{strategy}_{mode}_{start}_{end}"


def optuna_run_lock_name(strategy: str) -> str:
    return f"{strategy}_param_search_optuna"
