"""Risk models for ZenOTC SDK."""

from __future__ import annotations

from datetime import datetime
from decimal import Decimal
from enum import Enum
from typing import List, Optional

from pydantic import Field

from zenotc.models.base import BaseModel


class LimitType(str, Enum):
    """Type of risk limit."""

    MAX_ORDER_SIZE = "max_order_size"
    MAX_POSITION_SIZE = "max_position_size"
    MAX_DAILY_VOLUME = "max_daily_volume"
    MAX_NOTIONAL_VALUE = "max_notional_value"
    MAX_EXPOSURE = "max_exposure"
    MAX_LOSS = "max_loss"


class RiskLimit(BaseModel):
    """Risk limit configuration."""

    limit_type: LimitType = Field(..., description="Type of limit")
    asset: Optional[str] = Field(None, description="Asset (None for portfolio-wide)")
    limit_value: Decimal = Field(..., description="Limit value")
    current_value: Decimal = Field(..., description="Current utilization")
    utilization_percentage: float = Field(..., description="Utilization percentage")
    is_breached: bool = Field(..., description="Whether limit is breached")
    updated_at: datetime = Field(..., description="Last update timestamp")

    @property
    def remaining(self) -> Decimal:
        """Get remaining capacity."""
        return max(Decimal("0"), self.limit_value - self.current_value)


class RiskLimits(BaseModel):
    """All risk limits for a user."""

    limits: List[RiskLimit] = Field(..., description="List of risk limits")
    updated_at: datetime = Field(..., description="Last update timestamp")

    def get_limit(
        self, limit_type: LimitType, asset: Optional[str] = None
    ) -> Optional[RiskLimit]:
        """Get a specific limit."""
        for limit in self.limits:
            if limit.limit_type == limit_type and limit.asset == asset:
                return limit
        return None

    def get_breached_limits(self) -> List[RiskLimit]:
        """Get all breached limits."""
        return [limit for limit in self.limits if limit.is_breached]

    @property
    def has_breached_limits(self) -> bool:
        """Check if any limit is breached."""
        return any(limit.is_breached for limit in self.limits)


class PreTradeCheckRequest(BaseModel):
    """Request for pre-trade risk check."""

    side: str = Field(..., pattern="^(buy|sell)$", description="Order side")
    asset: str = Field(..., min_length=1, max_length=10, description="Asset symbol")
    quantity: Decimal = Field(..., gt=0, description="Order quantity")
    price: Decimal = Field(..., gt=0, description="Order price")


class PreTradeCheckResult(BaseModel):
    """Result of pre-trade risk check."""

    approved: bool = Field(..., description="Whether trade is approved")
    reason: Optional[str] = Field(None, description="Rejection reason if not approved")
    warnings: List[str] = Field(default_factory=list, description="Warning messages")
    checks_performed: List[str] = Field(..., description="List of checks performed")
    available_quantity: Optional[Decimal] = Field(
        None, description="Maximum quantity allowed if rejected"
    )
    limit_breaches: List[RiskLimit] = Field(
        default_factory=list, description="Limits that would be breached"
    )
    estimated_new_exposure: Optional[Decimal] = Field(
        None, description="Estimated exposure after trade"
    )
    timestamp: datetime = Field(..., description="Check timestamp")

    @property
    def has_warnings(self) -> bool:
        """Check if there are any warnings."""
        return len(self.warnings) > 0
