"""
=========================================
CV6 AI Trading OS — Backtest Models
Pydantic models for API request/response.
=========================================
"""
from __future__ import annotations

from typing import Any, Dict, List, Optional
from pydantic import BaseModel, Field


# ── Run request ───────────────────────────────────────────────────────────────

class BacktestRunRequest(BaseModel):
    # Mode
    mode: str = Field("QUICK", description="QUICK | PORTFOLIO | REPLAY | PAPER_REPLAY")

    # Symbol(s)
    symbol:  Optional[str]       = None    # single symbol (QUICK mode)
    symbols: Optional[List[str]] = None    # multiple symbols (PORTFOLIO / REPLAY)

    # Date range
    from_date:  Optional[str] = None       # YYYY-MM-DD
    to_date:    Optional[str] = None       # YYYY-MM-DD
    # Legacy aliases
    start_date: Optional[str] = None
    end_date:   Optional[str] = None

    # Capital & risk
    capital:             float = 100000.0
    risk_pct:            float = 1.0
    max_daily_loss:      float = 5000.0
    max_open_positions:  int   = 5
    max_trades_per_day:  int   = 20

    # Strategies to test
    strategies: List[str] = Field(
        default_factory=lambda: ["EMA_CROSSOVER", "VWAP", "SUPERTREND", "RSI_REVERSAL"]
    )

    # Data interval
    interval: str = "1d"   # 1d | 1h | 30m | 15m | 5m

    # AI mode
    use_ai:       bool  = False
    ai_threshold: float = 60.0

    # Broker simulation
    slippage_pct: float = 0.0003   # 0.03% default

    # Replay speed
    replay_speed: float = 1.0   # candles/second

    # Legacy fields (backward compatibility)
    strategy:         Optional[str]   = None
    strategy_name:    Optional[str]   = None
    initial_capital:  Optional[float] = None
    risk_percent:     Optional[float] = None
    trading_end:      str = "15:15"


# ── Session control ───────────────────────────────────────────────────────────

class BacktestControlRequest(BaseModel):
    session_id: str


class BacktestSpeedRequest(BaseModel):
    session_id: str
    speed: float = 1.0


class BacktestCompareRequest(BaseModel):
    session_id_a: str
    session_id_b: str


# ── Legacy models (kept for backward compatibility) ────────────────────────────

class BacktestRequest(BaseModel):
    """Legacy single-request model — maps to BacktestRunRequest."""
    symbol:          str   = "NIFTY"
    strategy:        str   = "EMA"
    from_date:       Optional[str] = None
    to_date:         Optional[str] = None
    capital:         float = 100000.0
    risk_percent:    float = 1.0
    strategy_name:   Optional[str]   = None
    initial_capital: Optional[float] = None
    start_date:      Optional[str]   = None
    end_date:        Optional[str]   = None

    def to_run_request(self) -> BacktestRunRequest:
        return BacktestRunRequest(
            mode="QUICK",
            symbol=self.symbol,
            from_date=self.from_date or self.start_date,
            to_date=self.to_date or self.end_date,
            capital=self.initial_capital or self.capital,
            risk_pct=self.risk_percent,
            strategies=[self.strategy_name or self.strategy or "EMA_CROSSOVER"],
        )


class TradeLog(BaseModel):
    date:    str
    side:    str
    entry:   float
    exit:    float
    qty:     int
    pnl:     float
    pnl_pct: float


class BacktestResponse(BaseModel):
    symbol:           str
    strategy:         str
    total_trades:     int
    winning_trades:   int
    losing_trades:    int
    win_rate:         float
    win_rate_pct:     float
    net_profit:       float
    net_pnl:          float
    total_pnl:        float
    return_pct:       float
    max_drawdown:     float
    sharpe_ratio:     float
    cagr:             float
    initial_capital:  float
    final_capital:    float
    trades_list:      List[TradeLog] = []
    # Extended analytics — all computed from actual simulation; None means not available
    profit_factor:    Optional[float] = None
    sortino_ratio:    Optional[float] = None
    expectancy:       Optional[float] = None
    avg_win:          Optional[float] = None
    avg_loss:         Optional[float] = None
    largest_win:      Optional[float] = None
    largest_loss:     Optional[float] = None
    recovery_factor:  Optional[float] = None
    total_charges:    float = 0.0
    session_id:       Optional[str] = None
