"""
시장 레짐 감지 모듈
- 코스피 지수 수준에 따른 시장 레짐 분류
- 코스피 6300 목표 수준에서의 모델 적합성 평가
- 레짐별 전략 파라미터 자동 조정
"""

from dataclasses import dataclass
from enum import Enum
from typing import Optional, Dict


class MarketRegime(Enum):
    BULL_EXTREME = "bull_extreme"   # 코스피 5000+ (역사적 극고점, 6300 시나리오)
    BULL_STRONG  = "bull_strong"    # 코스피 3500~5000 (강한 상승장)
    BULL_NORMAL  = "bull_normal"    # 코스피 2500~3500 (정상 상승장)
    SIDEWAYS     = "sideways"       # 코스피 2000~2500 (횡보)
    BEAR_MILD    = "bear_mild"      # 코스피 1500~2000 (약세)
    BEAR_SEVERE  = "bear_severe"    # 코스피 1500 미만 (심각한 약세)


@dataclass
class RegimeAnalysis:
    """레짐 분석 결과"""
    regime: MarketRegime
    kospi_level: float
    description: str
    recommended_strategy: str
    buy_threshold_adj: float    # 매수 임계값 조정치 (+: 더 엄격, -: 완화)
    position_size_adj: float    # 포지션 크기 조정 배수 (1.0 = 기본)
    lstm_weight_adj: float      # LSTM 앙상블 가중치 조정 (+0.1 = 10% 증가)
    model_recommendation: str   # 모델 유지/교체 권고
    risk_level: str             # LOW / MEDIUM / HIGH / EXTREME


class MarketRegimeDetector:
    """
    코스피 지수 수준 기반 시장 레짐 감지기

    코스피 6300 시나리오:
    - 현재 한국 증시 역대 최고점(2021년 3300) 대비 약 2배 수준
    - BULL_EXTREME 레짐에 해당 → LSTM 단독 의존 지양, Transformer/Mamba 검토 필요
    - 추세 추종 강화 + 고점 리스크 관리 병행
    """

    # 레짐별 상세 파라미터
    _REGIME_PARAMS: Dict[MarketRegime, dict] = {
        MarketRegime.BULL_EXTREME: {
            "description": "코스피 극강세장 5000+ (6300 시나리오)",
            "recommended_strategy": (
                "추세 추종 극대화, 트레일링 스탑 확대(ATR×4), "
                "고점 과열 구간으로 포지션 축소 병행"
            ),
            "buy_threshold_adj": -0.04,   # 강세 모멘텀 → 진입 소폭 완화
            "position_size_adj": 0.75,    # 고점 리스크로 포지션 축소
            "lstm_weight_adj": -0.12,     # LSTM 비중 축소 (비선형 가격 동작)
            "model_recommendation": (
                "Temporal Fusion Transformer(TFT) 또는 Mamba(SSM) 교체 권고 - "
                "LSTM은 극강세 과열 구간에서 비선형 가격 동작 포착 한계"
            ),
            "risk_level": "EXTREME",
        },
        MarketRegime.BULL_STRONG: {
            "description": "코스피 강상승장 3500~5000",
            "recommended_strategy": "추세 추종, 모멘텀 강화, 손절 완화(ATR×2.5)",
            "buy_threshold_adj": -0.03,
            "position_size_adj": 1.1,
            "lstm_weight_adj": 0.05,
            "model_recommendation": "현재 LSTM v3 적합 - 성능 모니터링 유지",
            "risk_level": "MEDIUM",
        },
        MarketRegime.BULL_NORMAL: {
            "description": "코스피 정상 상승장 2500~3500",
            "recommended_strategy": "기본 전략 유지 (기술+LSTM+LLM 균형)",
            "buy_threshold_adj": 0.0,
            "position_size_adj": 1.0,
            "lstm_weight_adj": 0.0,
            "model_recommendation": "현재 LSTM v3 최적 환경",
            "risk_level": "LOW",
        },
        MarketRegime.SIDEWAYS: {
            "description": "코스피 횡보장 2000~2500",
            "recommended_strategy": "박스권 매매, LLM 감성 비중 확대, 빠른 익절",
            "buy_threshold_adj": 0.03,
            "position_size_adj": 0.85,
            "lstm_weight_adj": -0.05,
            "model_recommendation": "현재 LSTM v3 적합 - 감성 분석 가중치 강화",
            "risk_level": "LOW",
        },
        MarketRegime.BEAR_MILD: {
            "description": "코스피 약세장 1500~2000",
            "recommended_strategy": "현금 비중 확대(50%+), 방어주 선별 매수",
            "buy_threshold_adj": 0.08,
            "position_size_adj": 0.5,
            "lstm_weight_adj": 0.0,
            "model_recommendation": "현재 LSTM v3 적합 - 리스크 관리 파라미터 강화",
            "risk_level": "HIGH",
        },
        MarketRegime.BEAR_SEVERE: {
            "description": "코스피 극약세장 1500 미만",
            "recommended_strategy": "전면 현금화, 매수 중단",
            "buy_threshold_adj": 0.20,
            "position_size_adj": 0.2,
            "lstm_weight_adj": 0.0,
            "model_recommendation": "매크로 팩터 기반 방어 모델 전환 필요",
            "risk_level": "EXTREME",
        },
    }

    @classmethod
    def detect(
        cls,
        kospi_price: float,
        kospi_change_pct: float = 0.0,
        volatility_20d: float = 0.0,
    ) -> RegimeAnalysis:
        """
        코스피 지수 수준 + 변동성으로 시장 레짐 감지

        Args:
            kospi_price: 현재 코스피 지수 (예: 2600, 6300)
            kospi_change_pct: 전일 대비 등락률 (%)
            volatility_20d: 20일 변동성 (선택, 0이면 무시)

        Returns:
            RegimeAnalysis: 레짐 분석 결과 및 전략 파라미터
        """
        # 1. 지수 수준으로 기본 레짐 결정
        if kospi_price >= 5000:
            regime = MarketRegime.BULL_EXTREME
        elif kospi_price >= 3500:
            regime = MarketRegime.BULL_STRONG
        elif kospi_price >= 2500:
            regime = MarketRegime.BULL_NORMAL
        elif kospi_price >= 2000:
            regime = MarketRegime.SIDEWAYS
        elif kospi_price >= 1500:
            regime = MarketRegime.BEAR_MILD
        else:
            regime = MarketRegime.BEAR_SEVERE

        params = cls._REGIME_PARAMS[regime]

        # 2. 변동성 기반 포지션 사이징 추가 조정
        position_adj = params["position_size_adj"]
        if volatility_20d > 30:
            position_adj *= 0.6   # 극단적 변동성 → 추가 50% 축소
        elif volatility_20d > 20:
            position_adj *= 0.8   # 높은 변동성 → 20% 축소

        # 3. 급락 중 레짐 하향 조정 (패닉 감지)
        if kospi_change_pct <= -3.0:
            # 극단적 일일 급락 → 포지션 추가 축소
            position_adj *= 0.5
            print(f"[Regime] PANIC DETECTED (일일 {kospi_change_pct:.1f}%) → 포지션 50% 추가 축소")

        return RegimeAnalysis(
            regime=regime,
            kospi_level=kospi_price,
            description=params["description"],
            recommended_strategy=params["recommended_strategy"],
            buy_threshold_adj=params["buy_threshold_adj"],
            position_size_adj=round(position_adj, 3),
            lstm_weight_adj=params["lstm_weight_adj"],
            model_recommendation=params["model_recommendation"],
            risk_level=params["risk_level"],
        )

    @classmethod
    def validate_model_for_regime(
        cls,
        regime: MarketRegime,
        backtest_sharpe: Optional[float] = None,
        backtest_winrate: Optional[float] = None,
        backtest_mdd: Optional[float] = None,
    ) -> dict:
        """
        현재 LSTM v3 모델이 해당 레짐에서 적합한지 검증

        Returns:
            {
                "is_suitable": bool,
                "confidence_score": float (0~1),
                "recommendation": str,
                "should_replace": bool,
                "alternative_models": list[str],
                "reason": str,
            }
        """
        result = {
            "is_suitable": True,
            "confidence_score": 0.75,
            "recommendation": "현재 LSTM v3 모델 유지",
            "should_replace": False,
            "alternative_models": [],
            "reason": "정상 상승장 구간 - LSTM v3 최적 환경",
        }

        # 레짐 기반 기본 평가
        if regime == MarketRegime.BULL_EXTREME:
            result.update({
                "is_suitable": False,
                "confidence_score": 0.38,
                "recommendation": "Transformer 계열 모델 교체 강력 권고",
                "should_replace": True,
                "alternative_models": [
                    "Temporal Fusion Transformer (TFT) - 장기 시계열 최강",
                    "Mamba (SSM) - 초고속 추론 + 긴 컨텍스트",
                    "PatchTST - Transformer 기반 주가 예측 특화",
                    "TimesNet - 2D 시계열 변환 + CNN",
                    "N-BEATS / N-HiTS - 해석 가능 딥러닝",
                ],
                "reason": (
                    "코스피 5000+ 극강세장에서 LSTM은 비선형적 가격 급등 패턴을 "
                    "충분히 학습하지 못함. Attention 메커니즘만으로는 장기 상승 추세의 "
                    "복잡한 의존성 포착에 한계 존재."
                ),
            })
        elif regime == MarketRegime.BEAR_SEVERE:
            result.update({
                "is_suitable": False,
                "confidence_score": 0.30,
                "recommendation": "매크로 팩터 + Regime-Switching 모델 교체 권고",
                "should_replace": True,
                "alternative_models": [
                    "Regime-Switching LSTM (HMM + LSTM)",
                    "매크로 멀티팩터 모델 (환율, 금리, VIX 통합)",
                    "GRU + Attention (LSTM 경량 대안)",
                ],
                "reason": "극약세장에서는 기술적 지표보다 거시경제 팩터가 지배적",
            })
        elif regime == MarketRegime.BULL_STRONG:
            result.update({
                "confidence_score": 0.72,
                "reason": "강상승장 - LSTM 추세 학습 양호하나 성능 모니터링 필요",
            })
        elif regime == MarketRegime.SIDEWAYS:
            result.update({
                "confidence_score": 0.68,
                "reason": "횡보장 - LSTM 예측력 저하, LLM 감성 보완 필수",
                "recommendation": "현재 LSTM v3 유지 + LLM 감성 가중치 상향",
            })

        # 백테스트 결과 반영
        if backtest_sharpe is not None:
            if backtest_sharpe < 0:
                result["confidence_score"] *= 0.5
                result["should_replace"] = True
                result["recommendation"] += " ⚠️ Sharpe < 0 → 즉시 교체 검토"
            elif backtest_sharpe < 0.5:
                result["confidence_score"] *= 0.75
                result["recommendation"] += f" (Sharpe={backtest_sharpe:.2f} 미흡)"

        if backtest_winrate is not None and backtest_winrate < 45:
            result["confidence_score"] *= 0.8
            result["recommendation"] += f" (승률={backtest_winrate:.1f}% 미흡)"

        if backtest_mdd is not None and backtest_mdd < -25:
            result["confidence_score"] *= 0.7
            result["should_replace"] = True
            result["recommendation"] += f" ⚠️ MDD={backtest_mdd:.1f}% 과다"

        result["confidence_score"] = round(max(0.0, min(1.0, result["confidence_score"])), 3)
        return result

    @staticmethod
    def get_regime_label(kospi_price: float) -> str:
        """간략 레짐 라벨 반환 (로그/UI 표시용)"""
        if kospi_price >= 5000:
            return f"BULL_EXTREME({kospi_price:.0f})"
        elif kospi_price >= 3500:
            return f"BULL_STRONG({kospi_price:.0f})"
        elif kospi_price >= 2500:
            return f"BULL_NORMAL({kospi_price:.0f})"
        elif kospi_price >= 2000:
            return f"SIDEWAYS({kospi_price:.0f})"
        elif kospi_price >= 1500:
            return f"BEAR_MILD({kospi_price:.0f})"
        return f"BEAR_SEVERE({kospi_price:.0f})"
