"""
Trading Protection System

Prevents excessive losses by automatically pausing trading when risk thresholds are exceeded.

Inspired by common trading protection patterns, implemented from scratch for NexQuant.
"""

from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from typing import Optional
from enum import Enum


class ProtectionType(Enum):
    """Type of protection mechanism."""
    MAX_DRAWDOWN = "max_drawdown"
    COOLDOWN = "cooldown"
    STOPLOSS_GUARD = "stoploss_guard"
    LOW_PERFORMANCE = "low_performance"


class ProtectionScope(Enum):
    """What scope does this protection apply to?"""
    GLOBAL = "global"  # All trading
    FACTOR = "factor"  # Per-factor
    PORTFOLIO = "portfolio"  # Per portfolio


@dataclass
class ProtectionResult:
    """Result of a protection check."""
    should_block: bool  # True if trading should be blocked
    reason: str  # Why was it blocked?
    until: Optional[datetime] = None  # If time-based, when does it expire?
    protection_type: Optional[ProtectionType] = None
    severity: float = 0.0  # How severe is the issue (0-1)

    @property
    def is_active(self) -> bool:
        """Check if protection is currently active."""
        if not self.until:
            return self.should_block
        return datetime.now() < self.until and self.should_block


@dataclass
class ProtectionConfig:
    """Base configuration for a protection."""
    enabled: bool = True
    lookback_period_hours: int = 24  # How far back to look
    severity_threshold: float = 0.8  # At what severity to block


class BaseProtection(ABC):
    """
    Base class for all trading protections.

    Each protection checks specific conditions and returns ProtectionResult.
    Multiple protections can be combined in ProtectionManager.
    """

    def __init__(self, config: ProtectionConfig):
        self.config = config
        self.last_check: Optional[datetime] = None
        self.total_checks: int = 0
        self.total_blocks: int = 0

    @abstractmethod
    def check(
        self,
        returns: list[float],
        timestamps: list[datetime],
        current_equity: float,
        peak_equity: float,
        **kwargs
    ) -> ProtectionResult:
        """
        Check if protection should be triggered.

        Parameters
        ----------
        returns : list[float]
            Historical returns in lookback period
        timestamps : list[datetime]
            Timestamps of returns
        current_equity : float
            Current equity value
        peak_equity : float
            Peak equity value (highest ever)
        **kwargs
            Additional context (factor name, portfolio ID, etc.)

        Returns
        -------
        ProtectionResult
            Decision on whether to block trading
        """
        pass

    def calculate_drawdown(self, current: float, peak: float) -> float:
        """Calculate drawdown percentage (negative value)."""
        if peak == 0:
            return 0.0
        return (current - peak) / peak

    def calculate_max_consecutive_losses(self, returns: list[float]) -> int:
        """Find maximum consecutive losing trades."""
        max_losses = 0
        current_losses = 0

        for ret in returns:
            if ret < 0:
                current_losses += 1
                max_losses = max(max_losses, current_losses)
            else:
                current_losses = 0

        return max_losses

    def calculate_recent_loss_rate(self, returns: list[float]) -> float:
        """Calculate percentage of losing trades."""
        if not returns:
            return 0.0
        losses = sum(1 for r in returns if r < 0)
        return losses / len(returns)

    def record_check(self, blocked: bool = False):
        """Record that a check was performed."""
        self.total_checks += 1
        self.last_check = datetime.now()
        if blocked:
            self.total_blocks += 1

    def get_stats(self) -> dict:
        """Get protection statistics."""
        return {
            "type": self.__class__.__name__,
            "enabled": self.config.enabled,
            "total_checks": self.total_checks,
            "total_blocks": self.total_blocks,
            "block_rate": self.total_blocks / max(1, self.total_checks),
            "last_check": self.last_check.isoformat() if self.last_check else None
        }
