"""Type-safe configuration settings using Pydantic."""

from typing import Dict, List, Optional

from pydantic import BaseModel, Field, field_validator

from src.core.exceptions import ConfigurationError


class TradingSessionConfig(BaseModel):
    """Trading session configuration."""

    start_time: str = Field(..., description="Session start time (HH:MM)")
    end_time: str = Field(..., description="Session end time (HH:MM)")
    timezone: str = Field(default="America/New_York", description="Timezone")


class InstrumentConfig(BaseModel):
    """Instrument configuration."""

    symbol: str = Field(..., description="Instrument symbol")
    exchange: str = Field(..., description="Exchange name")
    contract_size: float = Field(..., description="Contract size")


class TradingConfig(BaseModel):
    """Trading configuration."""

    session: TradingSessionConfig
    instrument: InstrumentConfig


class DataConfig(BaseModel):
    """Data configuration."""

    raw_data_path: str = Field(..., description="Path to raw data")
    processed_data_path: str = Field(..., description="Path to processed data")
    labels_path: str = Field(..., description="Path to labels")
    screenshots_path: str = Field(..., description="Path to screenshots")
    timeframes: List[str] = Field(default=["1min", "5min", "15min"])


class ModelConfig(BaseModel):
    """Model configuration."""

    base_path: str = Field(..., description="Base path for models")
    pattern_graders_path: str = Field(..., description="Path to pattern graders")
    strategy_models_path: str = Field(..., description="Path to strategy models")
    min_labels_per_pattern: int = Field(default=200, ge=50)
    train_test_split: float = Field(default=0.8, ge=0.5, le=0.9)


class AppConfig(BaseModel):
    """Main application configuration."""

    name: str = Field(default="ICT ML Trading System")
    version: str = Field(default="0.1.0")
    environment: str = Field(default="development")
    debug: bool = Field(default=False)


class Config(BaseModel):
    """Root configuration model."""

    app: AppConfig
    trading: TradingConfig
    data: DataConfig
    models: ModelConfig

    @classmethod
    def from_dict(cls, config_dict: Dict) -> "Config":
        """
        Create Config from dictionary.

        Args:
            config_dict: Configuration dictionary

        Returns:
            Config instance

        Raises:
            ConfigurationError: If configuration is invalid
        """
        try:
            return cls(**config_dict)
        except Exception as e:
            raise ConfigurationError(
                f"Invalid configuration: {e}",
                context={"config_dict": config_dict},
            ) from e

