"""
Data Models with Validation
Using Pydantic for robust input validation
"""

from typing import List, Dict, Optional, Any
from pydantic import BaseModel, Field, validator, constr
from datetime import datetime
from enum import Enum


class OptimizationMode(str, Enum):
    """Modes d'optimisation disponibles"""
    QUICK = "quick"
    GRID = "grid"
    GENETIC = "genetic"
    FULL = "full"


class TradingConfig(BaseModel):
    """Configuration de trading avec validation"""
    STOP_LOSS_PERCENT: float = Field(ge=0.0, le=20.0, description="Stop loss en %")
    TAKE_PROFIT_PERCENT: float = Field(ge=0.0, le=50.0, description="Take profit en %")
    MAX_ORDER_SIZE: Optional[int] = Field(default=None, ge=1, le=10000, description="Taille max de l'ordre")
    RSI_PERIOD: int = Field(ge=5, le=50, description="Période RSI")
    RSI_OVERSOLD: float = Field(ge=10.0, le=40.0, description="Niveau survente RSI")
    RSI_OVERBOUGHT: float = Field(ge=60.0, le=90.0, description="Niveau surachat RSI")
    EMA_SHORT: int = Field(ge=3, le=50, description="Période EMA courte")
    EMA_LONG: int = Field(ge=10, le=200, description="Période EMA longue")
    BB_PERIOD: int = Field(ge=5, le=50, description="Période Bollinger Bands")
    BB_STD: float = Field(ge=1.0, le=4.0, description="Écart-type Bollinger")
    REQUIRED_SIGNALS: int = Field(ge=1, le=5, description="Signaux requis")
    restart_bot: Optional[bool] = Field(default=False, description="Redémarrer le bot")

    @validator('EMA_LONG')
    def ema_long_must_be_greater(cls, v, values):
        """Vérifier que EMA_LONG > EMA_SHORT"""
        if 'EMA_SHORT' in values and v <= values['EMA_SHORT']:
            raise ValueError('EMA_LONG doit être > EMA_SHORT')
        return v


class OptimizationRequest(BaseModel):
    """Requête d'optimisation"""
    mode: OptimizationMode = Field(default=OptimizationMode.QUICK)
    symbols: List[constr(min_length=3, max_length=20)] = Field(
        default=['BTCUSDT', 'ETHUSDT', 'BNBUSDT'],
        min_items=1,
        max_items=100
    )
    currentConfig: Optional[Dict[str, Any]] = Field(default=None)

    @validator('symbols')
    def validate_symbols(cls, v):
        """Valider les symboles"""
        for symbol in v:
            if not symbol.endswith('USDT') and not symbol.endswith('USDC'):
                raise ValueError(f'Symbol {symbol} must end with USDT or USDC')
        return v


class SettingsUpdate(BaseModel):
    """Mise à jour des paramètres du bot"""
    auto_trade: Optional[bool] = None
    max_positions: Optional[int] = Field(None, ge=1, le=50)
    position_size: Optional[float] = Field(None, ge=1.0, le=10000.0)
    risk_per_trade: Optional[float] = Field(None, ge=0.1, le=10.0)


class ForceCloseRequest(BaseModel):
    """Requête de fermeture forcée"""
    symbol: constr(min_length=3, max_length=20)


class WatchlistRequest(BaseModel):
    """Requête de sauvegarde de watchlist"""
    symbols: List[constr(min_length=3, max_length=20)] = Field(
        min_items=1,
        max_items=200
    )

    @validator('symbols')
    def validate_symbols(cls, v):
        """Valider les symboles"""
        for symbol in v:
            if not symbol.endswith('USDT') and not symbol.endswith('USDC'):
                raise ValueError(f'Symbol {symbol} must end with USDT or USDC')
        return list(set(v))  # Dédupliquer


class APIResponse(BaseModel):
    """Réponse API standard"""
    success: bool
    message: Optional[str] = None
    data: Optional[Dict[str, Any]] = None
    error: Optional[str] = None


class Position(BaseModel):
    """Modèle d'une position"""
    symbol: str
    entry_price: float
    quantity: float
    timestamp: str
    stop_loss: Optional[float] = None
    take_profit: Optional[float] = None


class Trade(BaseModel):
    """Modèle d'un trade"""
    symbol: str
    side: str
    entry_price: float
    exit_price: float
    quantity: float
    pnl: float
    pnl_pct: float
    reason: str
    entry_time: str
    exit_time: str
