"""Run-level backtesting configuration contracts (account, execution, broker, modeling)."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import TYPE_CHECKING

import pandas as pd

if TYPE_CHECKING:
    from volatility_trading.options import (
        MarginModel,
        PriceModel,
        RiskEstimator,
        ScenarioGenerator,
    )

    from .margin import MarginPolicy
    from .options_engine.lifecycle import HedgeExecutionModel, OptionExecutionModel


def _default_pricer() -> PriceModel:
    """Create default option pricer for one backtest run config."""
    from volatility_trading.options import BlackScholesPricer

    return BlackScholesPricer()


def _default_scenario_generator() -> ScenarioGenerator:
    """Create default stress-scenario generator for one backtest run config."""
    from volatility_trading.options import FixedGridScenarioGenerator

    return FixedGridScenarioGenerator()


def _default_risk_estimator() -> RiskEstimator:
    """Create default risk estimator for one backtest run config."""
    from volatility_trading.options import StressLossRiskEstimator

    return StressLossRiskEstimator()


def _default_option_execution_model() -> OptionExecutionModel:
    """Create default option execution model for one backtest run config."""
    from .options_engine.lifecycle import BidAskFeeOptionExecutionModel

    return BidAskFeeOptionExecutionModel()


def _default_hedge_execution_model() -> HedgeExecutionModel:
    """Create default hedge execution model for one backtest run config."""
    from .options_engine.lifecycle import FixedBpsHedgeExecutionModel

    return FixedBpsHedgeExecutionModel()


@dataclass(frozen=True)
class AccountConfig:
    """Account-level capital configuration for one backtest run."""

    initial_capital: float = 100_000.0


@dataclass(frozen=True)
class ExecutionConfig:
    """Execution assumptions used by entry/exit lifecycle pricing."""

    option_execution_model: OptionExecutionModel = field(
        default_factory=_default_option_execution_model
    )
    hedge_execution_model: HedgeExecutionModel = field(
        default_factory=_default_hedge_execution_model
    )

    def __post_init__(self) -> None:
        if self.option_execution_model is None:
            raise ValueError("option_execution_model must be configured")
        if self.hedge_execution_model is None:
            raise ValueError("hedge_execution_model must be configured")


@dataclass(frozen=True)
class MarginConfig:
    """Broker margin primitives used by sizing and margin-account lifecycle."""

    model: MarginModel | None = None
    policy: MarginPolicy | None = None


@dataclass(frozen=True)
class BrokerConfig:
    """Execution venue / broker rules for one backtest run."""

    margin: MarginConfig = field(default_factory=MarginConfig)


@dataclass(frozen=True)
class ModelingConfig:
    """Runtime pricing/risk engines used by sizing and lifecycle valuation."""

    pricer: PriceModel = field(default_factory=_default_pricer)
    scenario_generator: ScenarioGenerator = field(
        default_factory=_default_scenario_generator
    )
    risk_estimator: RiskEstimator = field(default_factory=_default_risk_estimator)


@dataclass(frozen=True)
class BacktestRunConfig:
    """Run-level backtesting configuration for one simulation."""

    account: AccountConfig = field(default_factory=AccountConfig)
    execution: ExecutionConfig = field(default_factory=ExecutionConfig)
    broker: BrokerConfig = field(default_factory=BrokerConfig)
    modeling: ModelingConfig = field(default_factory=ModelingConfig)
    start_date: pd.Timestamp | None = None
    end_date: pd.Timestamp | None = None

    def __post_init__(self) -> None:
        if self.start_date is not None and self.end_date is not None:
            if pd.Timestamp(self.start_date) > pd.Timestamp(self.end_date):
                raise ValueError("start_date must be <= end_date")
