"""Configuration management with validation."""

import json
import os
from pathlib import Path
from typing import Any, Optional
from pydantic import BaseModel, Field
from pydantic_settings import BaseSettings, SettingsConfigDict


class CoreConfig(BaseModel):
    """Core bot configuration."""
    enabled: bool = True
    mode: str = Field(default="dry_run", pattern="^(dry_run|live|watch)$")
    interval: int = Field(default=60, ge=1)
    max_retries: int = Field(default=3, ge=0)
    retry_delay: int = Field(default=5, ge=0)


class ExchangeConfig(BaseModel):
    """Exchange configuration."""
    name: str = Field(default="kraken", pattern="^(kraken|binance|coinbase)$")
    api_key: Optional[str] = None
    api_secret: Optional[str] = None
    sandbox: bool = True
    rate_limit: dict = Field(default_factory=lambda: {
        "orders_per_second": 1,
        "requests_per_second": 10
    })


class TradingConfig(BaseModel):
    """Trading parameters."""
    symbol: str = "XBT/USD"
    stake_amount: float = Field(default=100, ge=0)
    max_position_size: Optional[float] = None
    max_daily_trades: int = Field(default=10, ge=0)
    stop_loss: Optional[float] = None
    take_profit: Optional[float] = None
    trailing_stop: bool = False


class StrategyConfig(BaseModel):
    """Strategy configuration."""
    name: str
    params: dict = Field(default_factory=dict)


class DatabaseConfig(BaseModel):
    """Database configuration."""
    path: str = "trading_bot.db"
    backup_enabled: bool = True
    backup_interval: int = 3600


class TelegramConfig(BaseModel):
    """Telegram notification config."""
    enabled: bool = False
    token: Optional[str] = None
    chat_id: Optional[str] = None


class LogConfig(BaseModel):
    """Logging configuration."""
    level: str = Field(default="INFO", pattern="^(DEBUG|INFO|WARNING|ERROR)$")


class NotificationsConfig(BaseModel):
    """Notifications configuration."""
    telegram: TelegramConfig = Field(default_factory=TelegramConfig)
    log: LogConfig = Field(default_factory=LogConfig)


class BotConfig(BaseSettings):
    """Main bot configuration."""
    model_config = SettingsConfigDict(
        env_file=".env",
        env_prefix="BOT_",
        case_sensitive=False,
        extra="ignore"
    )
    
    core: CoreConfig = Field(default_factory=CoreConfig)
    exchange: ExchangeConfig = Field(default_factory=ExchangeConfig)
    trading: TradingConfig = Field(default_factory=TradingConfig)
    strategy: StrategyConfig
    database: DatabaseConfig = Field(default_factory=DatabaseConfig)
    notifications: NotificationsConfig = Field(default_factory=NotificationsConfig)
    
    def __init__(self, config_path: Optional[str] = None, **values):
        """Load config from file or environment."""
        if config_path and os.path.exists(config_path):
            with open(config_path, 'r') as f:
                file_config = json.load(f)
            # Merge file config with env/defaults
            values = {**file_config, **values}
        
        super().__init__(**values)
    
    @classmethod
    def load(cls, config_path: Optional[str] = None) -> "BotConfig":
        """Load configuration from file or environment."""
        if not config_path:
            # Try default locations
            for path in ["config.json", "config/config.json", "../config.json"]:
                if os.path.exists(path):
                    config_path = path
                    break
        
        return cls(config_path=config_path)
    
    def validate(self) -> bool:
        """Validate configuration."""
        # Check required exchange credentials for live mode
        if self.core.mode == "live" and self.exchange.name == "kraken":
            if not self.exchange.api_key or not self.exchange.api_secret:
                raise ValueError("API key and secret required for live mode")
        return True


def get_config(config_path: Optional[str] = None) -> BotConfig:
    """Get bot configuration."""
    config = BotConfig.load(config_path)
    config.validate()
    return config
