"""Pre-built scenario library for synthetic market backtesting.

Defines 12 scenarios covering diverse market regimes. Each scenario is a
ScenarioConfig that specifies market dynamics, event characteristics, and
signal coupling strength.

Key scenarios for overfitting detection:
  no_signal     → signal_strength=0.0 → strategy must return ~0
  strong_signal → signal_strength=0.6 → strategy must capture alpha

Scenario groups for targeted analysis:
  trend      → steady_bull, steady_bear, prolonged_bear
  volatility → low_vol_grind, high_vol_chop, vix_spike
  regime     → regime_switch, crash_v_recovery
  signal     → no_signal, strong_signal
  structural → sector_rotation, liquidity_drought
  quick      → steady_bull, steady_bear, no_signal (fast validation)
"""
from __future__ import annotations

from dataclasses import dataclass, field

from libs.backtest.scenarios.price_gen import PriceRegime
from libs.backtest.scenarios.macro_gen import VIXConfig, HYSpreadConfig
from libs.backtest.scenarios.event_gen import EventDistribution


@dataclass
class ScenarioConfig:
    """Complete specification of a synthetic market scenario."""

    name: str
    description: str

    # Market dynamics
    price_regimes: list[PriceRegime]
    """Ordered sequence of market regime segments."""
    vix_config: VIXConfig = field(default_factory=VIXConfig)
    hy_config: HYSpreadConfig = field(default_factory=HYSpreadConfig)

    # Event characteristics
    event_distribution: EventDistribution = field(default_factory=EventDistribution)

    # Signal coupling
    signal_strength: float = 0.35
    """0.0=pure noise, ~0.35=realistic SNR, 0.6=strong alpha."""
    signal_decay_days: int = 10
    """Days over which post-event signal drift decays."""
    false_positive_rate: float = 0.15
    """Fraction of qualifying events that produce negative returns (traps)."""

    # Simulation parameters
    n_symbols: int = 200
    """Number of unique synthetic tickers in the universe."""
    seed: int | None = None
    """Random seed for reproducibility (None = non-deterministic)."""


# ---------------------------------------------------------------------------
# Helper: bear-market event distribution (weaker signals, more negative reactions)
# ---------------------------------------------------------------------------

def _bear_event_dist(reaction_return_mean: float = -0.010) -> EventDistribution:
    return EventDistribution(
        reaction_return_mean=reaction_return_mean,
        reaction_return_std=0.065,
        event_directions={
            "bullish": 0.30,
            "mixed": 0.30,
            "unknown": 0.25,
            "bearish": 0.15,
        },
        volume_ratio_mean=2.2,
        signal_strength_mean=0.58,
        market_temperature_mean=1.2,
        volatility_20d_mean=0.38,
    )


def _stress_event_dist() -> EventDistribution:
    return EventDistribution(
        reaction_return_mean=0.000,
        reaction_return_std=0.080,
        event_directions={
            "bullish": 0.35,
            "mixed": 0.35,
            "unknown": 0.20,
            "bearish": 0.10,
        },
        volume_ratio_mean=2.5,
        signal_strength_mean=0.60,
        market_temperature_mean=1.5,
        volatility_20d_mean=0.42,
        rsi_14_mean=45.0,
        bb_position_mean=0.40,
    )


# ---------------------------------------------------------------------------
# Pre-built scenarios
# ---------------------------------------------------------------------------

STEADY_BULL = ScenarioConfig(
    name="steady_bull",
    description="Sustained bull market: +15% drift, 14% vol. Baseline profitable environment.",
    price_regimes=[
        PriceRegime(annualized_drift=0.15, annualized_vol=0.14, duration_days=252),
    ],
    vix_config=VIXConfig(base_level=14.0, mean_reversion=5.0, volatility=4.0),
    hy_config=HYSpreadConfig(base_level=3.5, mean_reversion=3.0, volatility=0.8),
    signal_strength=0.35,
    seed=1001,
)

STEADY_BEAR = ScenarioConfig(
    name="steady_bear",
    description="Sustained bear market: -20% drift, 22% vol. Tests macro regime filter (Gate 0).",
    price_regimes=[
        PriceRegime(annualized_drift=-0.20, annualized_vol=0.22, duration_days=252),
    ],
    vix_config=VIXConfig(base_level=28.0, mean_reversion=4.0, volatility=7.0),
    hy_config=HYSpreadConfig(base_level=7.0, mean_reversion=2.5, volatility=2.0),
    event_distribution=_bear_event_dist(reaction_return_mean=-0.010),
    signal_strength=0.35,
    seed=1002,
)

CRASH_V_RECOVERY = ScenarioConfig(
    name="crash_v_recovery",
    description=(
        "V-shaped crash + recovery: 60d normal → 20d crash (-40%/40% vol) → 172d recovery. "
        "Tests kill switch and drawdown protection."
    ),
    price_regimes=[
        PriceRegime(annualized_drift=0.10, annualized_vol=0.15, duration_days=60),
        PriceRegime(
            annualized_drift=-0.40, annualized_vol=0.40, duration_days=20,
            jump_prob=0.08, jump_mean=-0.05, jump_std=0.03,
        ),
        PriceRegime(annualized_drift=0.25, annualized_vol=0.20, duration_days=172),
    ],
    vix_config=VIXConfig(base_level=15.0, mean_reversion=3.0, volatility=8.0),
    hy_config=HYSpreadConfig(base_level=4.0, mean_reversion=2.0, volatility=2.5),
    signal_strength=0.35,
    seed=1003,
)

PROLONGED_BEAR = ScenarioConfig(
    name="prolonged_bear",
    description=(
        "2-year bear market: -15% drift, 25% vol over 504 trading days. "
        "Exceeds duration of any historical bear in training data."
    ),
    price_regimes=[
        PriceRegime(annualized_drift=-0.15, annualized_vol=0.25, duration_days=504),
    ],
    vix_config=VIXConfig(base_level=30.0, mean_reversion=3.5, volatility=8.0),
    hy_config=HYSpreadConfig(base_level=8.5, mean_reversion=2.0, volatility=2.5),
    event_distribution=_bear_event_dist(reaction_return_mean=-0.015),
    signal_strength=0.30,
    seed=1004,
)

LOW_VOL_GRIND = ScenarioConfig(
    name="low_vol_grind",
    description=(
        "Low-volatility grind: +8% drift, 8% vol. "
        "ATR shrinks → stop distances compress → fewer trades qualify."
    ),
    price_regimes=[
        PriceRegime(annualized_drift=0.08, annualized_vol=0.08, duration_days=252),
    ],
    vix_config=VIXConfig(base_level=11.0, mean_reversion=6.0, volatility=2.5),
    hy_config=HYSpreadConfig(base_level=2.8, mean_reversion=4.0, volatility=0.5),
    event_distribution=EventDistribution(
        volatility_20d_mean=0.15,
        volatility_20d_std=0.04,
        reaction_return_std=0.03,
    ),
    signal_strength=0.20,
    seed=1005,
)

HIGH_VOL_CHOP = ScenarioConfig(
    name="high_vol_chop",
    description=(
        "High-volatility sideways chop: 0% drift, 30% vol. "
        "Whipsaws test stop-loss resilience."
    ),
    price_regimes=[
        PriceRegime(annualized_drift=0.00, annualized_vol=0.30, duration_days=252),
    ],
    vix_config=VIXConfig(base_level=32.0, mean_reversion=4.0, volatility=9.0),
    hy_config=HYSpreadConfig(base_level=6.5, mean_reversion=2.5, volatility=2.0),
    event_distribution=_stress_event_dist(),
    signal_strength=0.25,
    seed=1006,
)

REGIME_SWITCH = ScenarioConfig(
    name="regime_switch",
    description=(
        "Rapid regime alternation: 4 × (60d bull / 63d bear) cycles. "
        "Tests whether macro gate adapts quickly to changing conditions."
    ),
    price_regimes=[
        PriceRegime(annualized_drift=0.15, annualized_vol=0.16, duration_days=60),
        PriceRegime(annualized_drift=-0.18, annualized_vol=0.24, duration_days=63),
        PriceRegime(annualized_drift=0.12, annualized_vol=0.16, duration_days=60),
        PriceRegime(annualized_drift=-0.15, annualized_vol=0.22, duration_days=69),
    ],
    vix_config=VIXConfig(base_level=20.0, mean_reversion=4.0, volatility=8.0),
    hy_config=HYSpreadConfig(base_level=5.0, mean_reversion=2.5, volatility=1.8),
    signal_strength=0.30,
    seed=1007,
)

VIX_SPIKE = ScenarioConfig(
    name="vix_spike",
    description=(
        "Normal market with 5 random VIX spike weeks (VIX 40+). "
        "Tests VIX continuous scaler and kill switch under stress clusters."
    ),
    price_regimes=[
        PriceRegime(annualized_drift=0.08, annualized_vol=0.16, duration_days=252),
    ],
    vix_config=VIXConfig(base_level=18.0, mean_reversion=3.0, volatility=12.0),
    hy_config=HYSpreadConfig(base_level=4.5, mean_reversion=2.5, volatility=2.0),
    signal_strength=0.35,
    seed=1008,
)

NO_SIGNAL = ScenarioConfig(
    name="no_signal",
    description=(
        "Pure noise: 0% drift, 16% vol, signal_strength=0.0. "
        "Market is flat so any positive return = OVERFIT to price patterns, not event alpha."
    ),
    price_regimes=[
        PriceRegime(annualized_drift=0.00, annualized_vol=0.16, duration_days=252),
    ],
    vix_config=VIXConfig(base_level=16.0, mean_reversion=5.0, volatility=4.5),
    hy_config=HYSpreadConfig(base_level=4.0, mean_reversion=3.0, volatility=1.0),
    signal_strength=0.00,
    seed=1009,
)

STRONG_SIGNAL = ScenarioConfig(
    name="strong_signal",
    description=(
        "Strong alpha: +10% drift, 16% vol, signal_strength=0.6. "
        "Strategy must capture meaningful positive returns."
    ),
    price_regimes=[
        PriceRegime(annualized_drift=0.10, annualized_vol=0.16, duration_days=252),
    ],
    vix_config=VIXConfig(base_level=16.0, mean_reversion=5.0, volatility=4.5),
    hy_config=HYSpreadConfig(base_level=4.0, mean_reversion=3.0, volatility=1.0),
    signal_strength=0.60,
    seed=1010,
)

SECTOR_ROTATION = ScenarioConfig(
    name="sector_rotation",
    description=(
        "Quarterly sector rotation: Tech underperforms while Healthcare/Financials rally. "
        "Tests sector concentration limits."
    ),
    price_regimes=[
        PriceRegime(annualized_drift=0.05, annualized_vol=0.18, duration_days=63),
        PriceRegime(annualized_drift=0.12, annualized_vol=0.16, duration_days=63),
        PriceRegime(annualized_drift=-0.05, annualized_vol=0.20, duration_days=63),
        PriceRegime(annualized_drift=0.08, annualized_vol=0.15, duration_days=63),
    ],
    vix_config=VIXConfig(base_level=20.0, mean_reversion=4.5, volatility=5.0),
    hy_config=HYSpreadConfig(base_level=4.5, mean_reversion=3.0, volatility=1.2),
    signal_strength=0.35,
    seed=1011,
)

LIQUIDITY_DROUGHT = ScenarioConfig(
    name="liquidity_drought",
    description=(
        "Liquidity drought: +5% drift, 18% vol, stock volumes drop 60%. "
        "Tests ADV fraction limits and position sizing."
    ),
    price_regimes=[
        PriceRegime(annualized_drift=0.05, annualized_vol=0.18, duration_days=252),
    ],
    vix_config=VIXConfig(base_level=22.0, mean_reversion=4.0, volatility=5.5),
    hy_config=HYSpreadConfig(base_level=5.0, mean_reversion=2.5, volatility=1.5),
    event_distribution=EventDistribution(
        avg_dollar_volume_mean=1_500_000.0,  # 70% lower than default
        avg_dollar_volume_std=800_000.0,
        volume_ratio_mean=1.2,
    ),
    signal_strength=0.30,
    seed=1012,
)


# ---------------------------------------------------------------------------
# Registry and groups
# ---------------------------------------------------------------------------

SCENARIO_REGISTRY: dict[str, ScenarioConfig] = {
    s.name: s
    for s in [
        STEADY_BULL,
        STEADY_BEAR,
        CRASH_V_RECOVERY,
        PROLONGED_BEAR,
        LOW_VOL_GRIND,
        HIGH_VOL_CHOP,
        REGIME_SWITCH,
        VIX_SPIKE,
        NO_SIGNAL,
        STRONG_SIGNAL,
        SECTOR_ROTATION,
        LIQUIDITY_DROUGHT,
    ]
}

SCENARIO_GROUPS: dict[str, list[str]] = {
    "trend": ["steady_bull", "steady_bear", "prolonged_bear"],
    "volatility": ["low_vol_grind", "high_vol_chop", "vix_spike"],
    "regime": ["regime_switch", "crash_v_recovery"],
    "signal": ["no_signal", "strong_signal"],
    "structural": ["sector_rotation", "liquidity_drought"],
    "quick": ["steady_bull", "steady_bear", "no_signal"],
    "all": list(SCENARIO_REGISTRY.keys()),
}
