"""Dashboard data models.

Pydantic models for API requests/responses and WebSocket messages.
"""

from __future__ import annotations

from datetime import datetime
from enum import Enum
from typing import Any, Dict, List, Optional

from pydantic import BaseModel, Field


class AlertLevel(str, Enum):
    """Alert severity levels."""

    INFO = "info"
    WARNING = "warning"
    ERROR = "error"
    CRITICAL = "critical"


class AlertType(str, Enum):
    """Types of alerts."""

    BANKRUPTCY = "bankruptcy"
    LARGE_LOSS = "large_loss"
    COST_OVERRUN = "cost_overrun"
    SYSTEM_ERROR = "system_error"
    TRADE_EXECUTED = "trade_executed"
    AGENT_STATUS_CHANGE = "agent_status_change"


class AgentStatus(BaseModel):
    """Agent status for dashboard display."""

    agent_id: str = Field(..., description="Unique agent identifier")
    balance: float = Field(..., description="Current balance")
    initial_capital: float = Field(..., description="Initial capital")
    status: str = Field(..., description="Survival status")
    skill_level: float = Field(..., ge=0.0, le=1.0, description="Current skill level")
    win_rate: float = Field(..., ge=0.0, le=1.0, description="Win rate")
    total_trades: int = Field(..., ge=0, description="Total trades executed")
    winning_trades: int = Field(..., ge=0, description="Number of winning trades")
    losing_trades: int = Field(..., ge=0, description="Number of losing trades")
    unlocked_factors: int = Field(..., ge=0, description="Number of unlocked factors")
    is_bankrupt: bool = Field(default=False, description="Whether agent is bankrupt")
    is_active: bool = Field(default=True, description="Whether agent is active")
    current_activity: Optional[str] = Field(default=None, description="Current activity")
    last_updated: datetime = Field(default_factory=datetime.now, description="Last update time")

    @property
    def profit_loss(self) -> float:
        """Calculate profit/loss."""
        return self.balance - self.initial_capital

    @property
    def profit_loss_pct(self) -> float:
        """Calculate profit/loss percentage."""
        if self.initial_capital <= 0:
            return 0.0
        return (self.profit_loss / self.initial_capital) * 100


class TradeRecord(BaseModel):
    """Trade record for dashboard."""

    trade_id: str = Field(..., description="Unique trade identifier")
    agent_id: str = Field(..., description="Agent that executed the trade")
    symbol: str = Field(..., description="Trading symbol")
    side: str = Field(..., description="Buy or sell")
    amount: float = Field(..., ge=0, description="Trade amount")
    price: float = Field(..., ge=0, description="Trade price")
    value: float = Field(..., ge=0, description="Total trade value")
    fee: float = Field(..., ge=0, description="Trading fee")
    pnl: Optional[float] = Field(default=None, description="Profit/loss from trade")
    is_win: Optional[bool] = Field(default=None, description="Whether trade was profitable")
    timestamp: datetime = Field(default_factory=datetime.now, description="Trade time")
    strategy: Optional[str] = Field(default=None, description="Strategy used")


class EquityPoint(BaseModel):
    """Single point in equity curve."""

    timestamp: datetime = Field(..., description="Timestamp")
    equity: float = Field(..., description="Total equity value")
    agent_id: Optional[str] = Field(default=None, description="Agent ID if agent-specific")


class PnLDistribution(BaseModel):
    """Profit/loss distribution."""

    bins: List[str] = Field(..., description="Bin labels")
    counts: List[int] = Field(..., description="Trade counts per bin")
    wins: List[int] = Field(..., description="Win counts per bin")
    losses: List[int] = Field(..., description="Loss counts per bin")


class CostBreakdown(BaseModel):
    """Cost breakdown by category."""

    token_costs: float = Field(..., ge=0, description="LLM token costs")
    trade_fees: float = Field(..., ge=0, description="Trading fees")
    data_costs: float = Field(..., ge=0, description="Market data costs")
    total: float = Field(..., ge=0, description="Total costs")


class SystemMetrics(BaseModel):
    """System-wide metrics."""

    total_agents: int = Field(..., ge=0, description="Total number of agents")
    active_agents: int = Field(..., ge=0, description="Number of active agents")
    bankrupt_agents: int = Field(..., ge=0, description="Number of bankrupt agents")
    total_trades: int = Field(..., ge=0, description="Total trades executed")
    total_volume: float = Field(..., ge=0, description="Total trading volume")
    total_pnl: float = Field(..., description="Total profit/loss")
    avg_win_rate: float = Field(..., ge=0, le=1.0, description="Average win rate")
    total_costs: CostBreakdown = Field(..., description="Total costs breakdown")
    system_equity: float = Field(..., description="Total system equity")
    timestamp: datetime = Field(default_factory=datetime.now, description="Metrics timestamp")


class AlertMessage(BaseModel):
    """Alert message for real-time notifications."""

    alert_id: str = Field(..., description="Unique alert identifier")
    alert_type: AlertType = Field(..., description="Type of alert")
    level: AlertLevel = Field(..., description="Alert severity level")
    agent_id: Optional[str] = Field(default=None, description="Related agent ID")
    title: str = Field(..., description="Alert title")
    message: str = Field(..., description="Alert message")
    details: Dict[str, Any] = Field(default_factory=dict, description="Additional details")
    timestamp: datetime = Field(default_factory=datetime.now, description="Alert time")
    acknowledged: bool = Field(default=False, description="Whether alert is acknowledged")


class DashboardState(BaseModel):
    """Complete dashboard state for initial load."""

    agents: List[AgentStatus] = Field(..., description="All agent statuses")
    recent_trades: List[TradeRecord] = Field(..., description="Recent trades")
    equity_curve: List[EquityPoint] = Field(..., description="Equity curve data")
    pnl_distribution: PnLDistribution = Field(..., description="PnL distribution")
    metrics: SystemMetrics = Field(..., description="System metrics")
    alerts: List[AlertMessage] = Field(..., description="Active alerts")
    timestamp: datetime = Field(default_factory=datetime.now, description="State timestamp")


class WebSocketMessage(BaseModel):
    """WebSocket message wrapper."""

    type: str = Field(..., description="Message type")
    data: Dict[str, Any] = Field(..., description="Message data")
    timestamp: datetime = Field(default_factory=datetime.now, description="Message timestamp")


class AgentDetail(AgentStatus):
    """Detailed agent information."""

    trade_history: List[TradeRecord] = Field(default_factory=list, description="Trade history")
    equity_curve: List[EquityPoint] = Field(default_factory=list, description="Agent equity curve")
    cost_breakdown: CostBreakdown = Field(..., description="Cost breakdown")
    balance_history: List[EquityPoint] = Field(default_factory=list, description="Balance history")
