"""
Strategy Analyzer Types Module - Phase 4
Enhanced data structures for trading strategy analysis with AI integration

This module defines specialized data structures for trading strategy analysis,
maintaining 100% compatibility with the reference implementation while adding
advanced AI-powered features and enhanced analytics.

Author: Pezhman Hajipour
Version: 3.0.0
Phase: 4
"""

from dataclasses import dataclass, field
from datetime import datetime, time
from typing import List, Optional, Dict, Literal, Callable, Any
from enum import Enum
from collections import defaultdict


class PatternType(str, Enum):
    """Types of trading patterns that can be identified"""
    TREND_FOLLOWING = "trend_following"
    MEAN_REVERSION = "mean_reversion"
    BREAKOUT = "breakout"
    SCALPING = "scalping"
    SWING = "swing"
    POSITION = "position"
    MOMENTUM = "momentum"
    CONTRARIAN = "contrarian"
    WHALE_FOLLOWING = "whale_following"  # Enhanced: Whale-specific pattern
    CROSS_CHAIN_ARBITRAGE = "cross_chain_arbitrage"  # Enhanced: Cross-chain pattern
    AI_PREDICTED = "ai_predicted"  # Enhanced: ML-discovered pattern
    UNKNOWN = "unknown"


class RecommendationType(str, Enum):
    """Types of strategy recommendations"""
    RISK_MANAGEMENT = "risk_management"
    POSITION_SIZING = "position_sizing"
    TIMING = "timing"
    DIVERSIFICATION = "diversification"
    EXIT_STRATEGY = "exit_strategy"
    ENTRY_STRATEGY = "entry_strategy"
    LEVERAGE = "leverage"
    COIN_SELECTION = "coin_selection"
    WHALE_STRATEGY = "whale_strategy"  # Enhanced: Whale-specific recommendations
    AI_OPTIMIZATION = "ai_optimization"  # Enhanced: ML-based recommendations
    CROSS_CHAIN = "cross_chain"  # Enhanced: Cross-chain opportunities


class AIStrategyInsight(str, Enum):
    """AI-generated strategic insights"""
    MARKET_REGIME_CHANGE = "market_regime_change"
    WHALE_MOVEMENT_PREDICTION = "whale_movement_prediction"
    OPTIMAL_ENTRY_TIMING = "optimal_entry_timing"
    PORTFOLIO_REBALANCE_NEEDED = "portfolio_rebalance_needed"
    RISK_ALERT = "risk_alert"
    OPPORTUNITY_DETECTED = "opportunity_detected"
    PERFORMANCE_DEGRADATION = "performance_degradation"


# Create alias for compatibility
AIInsightType = AIStrategyInsight


@dataclass
class TimeAnalysis:
    """
    Analysis of trading performance by time periods with enhanced AI features
    
    Attributes:
        hour_of_day: Performance by hour (0-23)
        day_of_week: Performance by day (0=Mon, 6=Sun)
        best_hour: Most profitable hour
        worst_hour: Least profitable hour
        best_day: Most profitable day of week
        worst_day: Least profitable day of week
        avg_trade_duration_minutes: Average time between entry and exit
        total_active_hours: Total hours with trading activity
        ai_optimal_hours: AI-recommended optimal trading hours
        market_sessions: Performance by market sessions (Asian, European, US)
    """
    hour_of_day: Dict[int, float] = field(default_factory=dict)
    day_of_week: Dict[int, float] = field(default_factory=dict)
    market_sessions: Dict[str, float] = field(default_factory=dict)
    best_hour: Optional[int] = None
    worst_hour: Optional[int] = None
    best_day: Optional[int] = None
    worst_day: Optional[int] = None
    ai_optimal_hours: List[int] = field(default_factory=list)
    avg_trade_duration_minutes: float = 0.0
    total_active_hours: int = 0
    
    @property
    def best_day_name(self) -> Optional[str]:
        """Get the name of the best performing day"""
        if self.best_day is None:
            return None
        days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
        return days[self.best_day]
    
    @property
    def worst_day_name(self) -> Optional[str]:
        """Get the name of the worst performing day"""
        if self.worst_day is None:
            return None
        days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
        return days[self.worst_day]
    
    def get_session_performance(self, session: str) -> float:
        """Get performance for a specific market session"""
        return self.market_sessions.get(session, 0.0)


@dataclass
class TradePattern:
    """
    Represents an identified trading pattern with AI enhancement
    
    Attributes:
        pattern_type: Type of pattern identified
        confidence: Confidence level (0-100)
        description: Human-readable description
        supporting_metrics: Metrics that support this pattern identification
        sample_trades_count: Number of trades analyzed for this pattern
        ai_confidence: AI-enhanced confidence score
        whale_indicators: Specific whale-related pattern indicators
        cross_chain_score: Cross-chain pattern relevance score
    """
    pattern_type: PatternType
    confidence: float
    description: str
    supporting_metrics: Dict[str, float] = field(default_factory=dict)
    sample_trades_count: int = 0
    ai_confidence: Optional[float] = None
    whale_indicators: Dict[str, float] = field(default_factory=dict)
    cross_chain_score: float = 0.0
    
    def __post_init__(self):
        """Validate pattern data"""
        if not 0 <= self.confidence <= 100:
            raise ValueError(f"Confidence must be between 0 and 100, got {self.confidence}")
        if self.ai_confidence is not None and not 0 <= self.ai_confidence <= 100:
            raise ValueError(f"AI confidence must be between 0 and 100, got {self.ai_confidence}")


@dataclass
class AIStrategyInsightData:
    """
    AI-generated strategic insight with actionable recommendations
    
    Attributes:
        insight_type: Type of AI insight
        confidence: AI confidence in the insight
        title: Short title of the insight
        description: Detailed explanation
        actionable_recommendations: List of specific actions to take
        expected_impact: Expected improvement if acted upon
        time_sensitivity: How quickly action should be taken
        related_metrics: Metrics this insight is based on
    """
    insight_type: AIInsightType
    confidence: float
    title: str
    description: str
    actionable_recommendations: List[str] = field(default_factory=list)
    expected_impact: str = ""
    time_sensitivity: Literal["IMMEDIATE", "DAILY", "WEEKLY"] = "DAILY"
    related_metrics: List[str] = field(default_factory=list)
    
    def __post_init__(self):
        """Validate insight data"""
        if not 0 <= self.confidence <= 100:
            raise ValueError(f"Confidence must be between 0 and 100, got {self.confidence}")


@dataclass
class StrategyMetrics:
    """
    Comprehensive metrics for evaluating a trading strategy with AI enhancements
    
    Attributes:
        strategy_name: Name/identifier of the strategy
        total_trades: Total number of trades
        winning_trades: Number of profitable trades
        losing_trades: Number of losing trades
        break_even_trades: Number of break-even trades
        
        gross_profit: Total profit from winning trades
        gross_loss: Total loss from losing trades (absolute value)
        net_profit: Net profit after all trades
        total_fees: Total fees paid
        
        win_rate: Percentage of winning trades
        profit_factor: Ratio of gross profit to gross loss
        risk_reward_ratio: Average win / Average loss
        expectancy: Expected profit per trade
        
        max_drawdown: Maximum peak-to-trough decline
        max_drawdown_percentage: Maximum drawdown as percentage
        recovery_factor: Net profit / Max drawdown
        
        sharpe_ratio: Risk-adjusted return metric
        sortino_ratio: Downside risk-adjusted return
        calmar_ratio: Return / Max drawdown
        
        avg_win: Average profit on winning trades
        avg_loss: Average loss on losing trades
        largest_win: Largest single winning trade
        largest_loss: Largest single losing trade
        
        avg_trade_size: Average position size
        max_consecutive_wins: Maximum consecutive winning trades
        max_consecutive_losses: Maximum consecutive losing losses
        
        coins_traded: List of coins traded
        most_traded_coin: Most frequently traded coin
        most_profitable_coin: Most profitable coin
        least_profitable_coin: Least profitable coin
        
        time_analysis: Time-based performance analysis
        identified_patterns: Detected trading patterns
        
        start_date: First trade date
        end_date: Last trade date
        analysis_timestamp: When this analysis was performed
        
        ai_insights: AI-generated strategic insights
        whale_performance: Performance metrics specific to whale trades
        cross_chain_performance: Cross-chain strategy performance
    """
    strategy_name: str = "Default Strategy"
    
    # Trade counts
    total_trades: int = 0
    winning_trades: int = 0
    losing_trades: int = 0
    break_even_trades: int = 0
    
    # Profit/Loss
    gross_profit: float = 0.0
    gross_loss: float = 0.0
    net_profit: float = 0.0
    total_fees: float = 0.0
    
    # Performance ratios
    win_rate: float = 0.0
    profit_factor: float = 0.0
    risk_reward_ratio: float = 0.0
    expectancy: float = 0.0
    
    # Risk metrics
    max_drawdown: float = 0.0
    max_drawdown_percentage: float = 0.0
    recovery_factor: float = 0.0
    
    # Advanced ratios
    sharpe_ratio: float = 0.0
    sortino_ratio: float = 0.0
    calmar_ratio: float = 0.0
    
    # Trade statistics
    avg_win: float = 0.0
    avg_loss: float = 0.0
    largest_win: float = 0.0
    largest_loss: float = 0.0
    
    # Position sizing
    avg_trade_size: float = 0.0
    avg_trade_value: float = 0.0
    total_volume: float = 0.0
    
    # Streaks
    max_consecutive_wins: int = 0
    max_consecutive_losses: int = 0
    current_streak: int = 0
    current_streak_type: Optional[Literal["WIN", "LOSS"]] = None
    
    # Coin analysis
    coins_traded: List[str] = field(default_factory=list)
    most_traded_coin: Optional[str] = None
    most_profitable_coin: Optional[str] = None
    least_profitable_coin: Optional[str] = None
    coin_performance: Dict[str, float] = field(default_factory=dict)
    
    # Time analysis
    time_analysis: Optional[TimeAnalysis] = None
    
    # Pattern recognition
    identified_patterns: List[TradePattern] = field(default_factory=list)
    primary_pattern: Optional[PatternType] = None
    
    # Date range
    start_date: Optional[datetime] = None
    end_date: Optional[datetime] = None
    analysis_timestamp: Optional[datetime] = None
    
    # Enhanced features for Phase 4
    ai_insights: List[AIStrategyInsight] = field(default_factory=list)
    whale_performance: Dict[str, float] = field(default_factory=dict)
    cross_chain_performance: Dict[str, float] = field(default_factory=dict)
    
    # PnL history for equity curve
    equity_curve: List[float] = field(default_factory=list)
    
    @property
    def net_profit_after_fees(self) -> float:
        """Net profit after subtracting all fees"""
        return self.net_profit - self.total_fees
    
    @property
    def avg_trade_pnl(self) -> float:
        """Average PnL per trade"""
        if self.total_trades == 0:
            return 0.0
        return self.net_profit / self.total_trades
    
    @property
    def trade_duration_days(self) -> int:
        """Number of days between first and last trade"""
        if not self.start_date or not self.end_date:
            return 0
        return (self.end_date - self.start_date).days
    
    @property
    def trades_per_day(self) -> float:
        """Average trades per day"""
        days = self.trade_duration_days
        if days == 0:
            return float(self.total_trades)
        return self.total_trades / days
    
    def is_profitable(self) -> bool:
        """Check if strategy is overall profitable"""
        return self.net_profit > 0
    
    def get_grade(self) -> str:
        """
        Get an overall grade for the strategy with AI-enhanced evaluation
        Based on multiple metrics and AI insights
        """
        score = 0
        
        # Win rate contribution (max 25 points)
        if self.win_rate >= 60:
            score += 25
        elif self.win_rate >= 50:
            score += 20
        elif self.win_rate >= 40:
            score += 15
        else:
            score += 5
        
        # Profit factor contribution (max 25 points)
        if self.profit_factor >= 2.0:
            score += 25
        elif self.profit_factor >= 1.5:
            score += 20
        elif self.profit_factor >= 1.2:
            score += 15
        elif self.profit_factor >= 1.0:
            score += 10
        else:
            score += 0
        
        # Risk/Reward contribution (max 25 points)
        if self.risk_reward_ratio >= 2.0:
            score += 25
        elif self.risk_reward_ratio >= 1.5:
            score += 20
        elif self.risk_reward_ratio >= 1.0:
            score += 15
        else:
            score += 5
        
        # Recovery factor contribution (max 25 points)
        if self.recovery_factor >= 3.0:
            score += 25
        elif self.recovery_factor >= 2.0:
            score += 20
        elif self.recovery_factor >= 1.0:
            score += 15
        elif self.recovery_factor > 0:
            score += 10
        else:
            score += 0
        
        # Convert score to grade
        if score >= 90:
            return "A+"
        elif score >= 80:
            return "A"
        elif score >= 70:
            return "B+"
        elif score >= 60:
            return "B"
        elif score >= 50:
            return "C+"
        elif score >= 40:
            return "C"
        elif score >= 30:
            return "D"
        else:
            return "F"


@dataclass
class StrategyRecommendation:
    """
    A recommendation for improving strategy performance with AI enhancement
    
    Attributes:
        recommendation_type: Category of recommendation
        priority: Priority level (1=highest, 5=lowest)
        title: Short title
        description: Detailed description
        expected_impact: Expected improvement description
        metrics_affected: List of metrics this would improve
        ai_generated: Whether this recommendation was generated by AI
        confidence: AI confidence in the recommendation
        implementation_difficulty: How difficult to implement (1=easy, 5=hard)
    """
    recommendation_type: RecommendationType
    priority: int
    title: str
    description: str
    expected_impact: str = ""
    metrics_affected: List[str] = field(default_factory=list)
    ai_generated: bool = False
    confidence: Optional[float] = None
    implementation_difficulty: Literal[1, 2, 3, 4, 5] = 3
    
    def __post_init__(self):
        """Validate recommendation data"""
        if not 1 <= self.priority <= 5:
            raise ValueError(f"Priority must be between 1 and 5, got {self.priority}")
        if self.confidence is not None and not 0 <= self.confidence <= 100:
            raise ValueError(f"Confidence must be between 0 and 100, got {self.confidence}")


@dataclass
class StrategyComparison:
    """
    Comparison between multiple strategies with AI-enhanced analysis
    
    Attributes:
        strategies: List of strategy metrics being compared
        best_overall: Name of best performing strategy
        best_by_metric: Best strategy for each key metric
        summary: Text summary of comparison
        comparison_timestamp: When this comparison was performed
        ai_recommendations: AI-generated strategy recommendations
        ensemble_suggestion: AI suggestion for combining strategies
    """
    strategies: List[StrategyMetrics] = field(default_factory=list)
    best_overall: Optional[str] = None
    best_by_metric: Dict[str, str] = field(default_factory=dict)
    summary: str = ""
    comparison_timestamp: Optional[datetime] = None
    ai_recommendations: List[AIStrategyInsight] = field(default_factory=list)
    ensemble_suggestion: Optional[str] = None
    
    def get_strategy(self, name: str) -> Optional[StrategyMetrics]:
        """Get a strategy by name"""
        for s in self.strategies:
            if s.strategy_name == name:
                return s
        return None
    
    def get_ranking(self) -> List[str]:
        """Get strategies ranked by overall performance (net profit)"""
        sorted_strategies = sorted(
            self.strategies,
            key=lambda s: s.net_profit,
            reverse=True
        )
        return [s.strategy_name for s in sorted_strategies]


@dataclass
class WhaleStrategyMetrics:
    """
    Specialized metrics for whale-following strategies
    
    Attributes:
        total_whale_trades: Number of trades following whale movements
        whale_success_rate: Success rate when following whales
        avg_whale_profit: Average profit from whale-following trades
        whale_copied_volume: Total volume copied from whales
        best_whale_address: Most profitable whale address
        whale_correlation: Correlation with whale movements
    """
    total_whale_trades: int = 0
    whale_success_rate: float = 0.0
    avg_whale_profit: float = 0.0
    whale_copied_volume: float = 0.0
    best_whale_address: Optional[str] = None
    whale_correlation: float = 0.0


@dataclass
class CrossChainStrategyMetrics:
    """
    Specialized metrics for cross-chain arbitrage strategies
    
    Attributes:
        cross_chain_trades: Number of cross-chain trades
        arbitrage_profit: Total arbitrage profit
        cross_chain_efficiency: Efficiency of cross-chain operations
        chain_spreads: Profitability by chain pairs
        cross_chain_volume: Total cross-chain volume
    """
    cross_chain_trades: int = 0
    arbitrage_profit: float = 0.0
    cross_chain_efficiency: float = 0.0
    chain_spreads: Dict[str, float] = field(default_factory=dict)
    cross_chain_volume: float = 0.0