"""
Engagement Analyzer

Analyzes engagement metrics, calculates engagement rates,
identifies trending content, and predicts virality.
"""

import logging
from typing import Dict, List, Any, Optional, Tuple
from datetime import datetime, timedelta
from dataclasses import dataclass
import statistics


@dataclass 
class EngagementMetrics:
    """Engagement metrics for content"""
    content_id: str
    source: str
    engagement_rate: float
    virality_score: float
    trend_direction: str  # 'up', 'down', 'stable'
    engagement_velocity: float
    relative_performance: float  # vs. source average


@dataclass
class TrendingContent:
    """Trending content identification"""
    content_id: str
    source: str
    title: str
    engagement_score: float
    velocity_score: float
    trend_type: str  # 'viral', 'steady_growth', 'spike'


class EngagementAnalyzer:
    """Analyzes engagement patterns and identifies trending content"""
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        
        # Source-specific engagement thresholds
        self.engagement_thresholds = {
            'youtube': {
                'high_engagement_rate': 0.05,  # 5%
                'viral_threshold': 0.10,       # 10%
                'view_velocity_threshold': 1000  # views per day
            },
            'instagram': {
                'high_engagement_rate': 0.03,  # 3%
                'viral_threshold': 0.08,       # 8%
                'view_velocity_threshold': 500
            },
            'wordpress': {
                'high_engagement_rate': 0.02,  # 2% (comments/views)
                'viral_threshold': 0.05,       # 5%
                'view_velocity_threshold': 100
            },
            'hvacrschool': {
                'high_engagement_rate': 0.01,  # 1%
                'viral_threshold': 0.03,       # 3%
                'view_velocity_threshold': 50
            }
        }

    def analyze_engagement_metrics(self, content_items: List[Dict[str, Any]], 
                                 source: str) -> List[EngagementMetrics]:
        """Analyze engagement metrics for content items from a specific source"""
        
        if not content_items:
            return []
            
        metrics = []
        
        # Calculate baseline metrics for the source
        engagement_rates = []
        for item in content_items:
            rate = self._calculate_engagement_rate(item, source)
            if rate > 0:
                engagement_rates.append(rate)
        
        avg_engagement = statistics.mean(engagement_rates) if engagement_rates else 0
        
        for item in content_items:
            try:
                metrics.append(self._analyze_single_item(item, source, avg_engagement))
            except Exception as e:
                self.logger.error(f"Error analyzing engagement for {item.get('id')}: {e}")
                
        return metrics

    def identify_trending_content(self, content_items: List[Dict[str, Any]], 
                                source: str, limit: int = 10) -> List[TrendingContent]:
        """Identify trending content based on engagement patterns"""
        
        trending = []
        
        for item in content_items:
            try:
                trend_score = self._calculate_trend_score(item, source)
                if trend_score > 0.6:  # Threshold for trending
                    trending.append(TrendingContent(
                        content_id=item.get('id', 'unknown'),
                        source=source,
                        title=item.get('title', 'No title')[:100],
                        engagement_score=self._calculate_engagement_rate(item, source),
                        velocity_score=self._calculate_velocity_score(item, source),
                        trend_type=self._classify_trend_type(item, source)
                    ))
            except Exception as e:
                self.logger.error(f"Error identifying trend for {item.get('id')}: {e}")
        
        # Sort by trend score and limit results
        trending.sort(key=lambda x: x.engagement_score + x.velocity_score, reverse=True)
        return trending[:limit]

    def calculate_source_summary(self, content_items: List[Dict[str, Any]], 
                                source: str) -> Dict[str, Any]:
        """Calculate summary engagement metrics for a source"""
        
        if not content_items:
            return {
                'total_items': 0,
                'avg_engagement_rate': 0,
                'total_engagement': 0,
                'trending_count': 0
            }
        
        engagement_rates = []
        total_engagement = 0
        
        for item in content_items:
            rate = self._calculate_engagement_rate(item, source)
            engagement_rates.append(rate)
            total_engagement += self._get_total_engagement(item, source)
        
        trending_content = self.identify_trending_content(content_items, source)
        
        return {
            'total_items': len(content_items),
            'avg_engagement_rate': statistics.mean(engagement_rates) if engagement_rates else 0,
            'median_engagement_rate': statistics.median(engagement_rates) if engagement_rates else 0,
            'total_engagement': total_engagement,
            'trending_count': len(trending_content),
            'high_performers': len([r for r in engagement_rates if r > self.engagement_thresholds.get(source, {}).get('high_engagement_rate', 0.03)])
        }

    def _analyze_single_item(self, item: Dict[str, Any], source: str, 
                           avg_engagement: float) -> EngagementMetrics:
        """Analyze engagement metrics for a single content item"""
        
        engagement_rate = self._calculate_engagement_rate(item, source)
        virality_score = self._calculate_virality_score(item, source)
        trend_direction = self._determine_trend_direction(item, source)
        engagement_velocity = self._calculate_velocity_score(item, source)
        
        # Calculate relative performance vs source average
        relative_performance = engagement_rate / avg_engagement if avg_engagement > 0 else 1.0
        
        return EngagementMetrics(
            content_id=item.get('id', 'unknown'),
            source=source,
            engagement_rate=engagement_rate,
            virality_score=virality_score,
            trend_direction=trend_direction,
            engagement_velocity=engagement_velocity,
            relative_performance=relative_performance
        )

    def _calculate_engagement_rate(self, item: Dict[str, Any], source: str) -> float:
        """Calculate engagement rate based on source type"""
        
        if source == 'youtube':
            views = item.get('views', 0) or item.get('view_count', 0)
            likes = item.get('likes', 0)
            comments = item.get('comments', 0)
            
            if views > 0:
                return (likes + comments) / views
                
        elif source == 'instagram':
            views = item.get('views', 0)
            likes = item.get('likes', 0) 
            comments = item.get('comments', 0)
            
            if views > 0:
                return (likes + comments) / views
            elif likes > 0:
                return comments / likes  # Fallback if no view count
                
        elif source in ['wordpress', 'hvacrschool']:
            # For blog content, use comments as engagement metric
            # This would need page view data integration in future
            comments = item.get('comments', 0)
            # Placeholder calculation - would need actual page view data
            estimated_views = max(100, comments * 50)  # Rough estimate
            return comments / estimated_views if estimated_views > 0 else 0
            
        return 0.0

    def _get_total_engagement(self, item: Dict[str, Any], source: str) -> int:
        """Get total engagement count for an item"""
        
        if source == 'youtube':
            return (item.get('likes', 0) + item.get('comments', 0))
            
        elif source == 'instagram':
            return (item.get('likes', 0) + item.get('comments', 0))
            
        elif source in ['wordpress', 'hvacrschool']:
            return item.get('comments', 0)
            
        return 0

    def _calculate_virality_score(self, item: Dict[str, Any], source: str) -> float:
        """Calculate virality score (0-1) based on engagement patterns"""
        
        engagement_rate = self._calculate_engagement_rate(item, source)
        thresholds = self.engagement_thresholds.get(source, {})
        
        viral_threshold = thresholds.get('viral_threshold', 0.05)
        high_engagement_threshold = thresholds.get('high_engagement_rate', 0.03)
        
        if engagement_rate >= viral_threshold:
            return min(1.0, engagement_rate / viral_threshold)
        elif engagement_rate >= high_engagement_threshold:
            return engagement_rate / viral_threshold
        else:
            return engagement_rate / high_engagement_threshold

    def _calculate_velocity_score(self, item: Dict[str, Any], source: str) -> float:
        """Calculate engagement velocity (engagement growth over time)"""
        
        # This is a simplified calculation - would need time-series data for true velocity
        publish_date = item.get('publish_date') or item.get('upload_date')
        
        if not publish_date:
            return 0.5  # Default score if no date available
            
        try:
            if isinstance(publish_date, str):
                pub_date = datetime.fromisoformat(publish_date.replace('Z', '+00:00'))
            else:
                pub_date = publish_date
                
            days_old = (datetime.now() - pub_date.replace(tzinfo=None)).days
            
            if days_old <= 0:
                days_old = 1  # Prevent division by zero
                
            total_engagement = self._get_total_engagement(item, source)
            velocity = total_engagement / days_old
            
            threshold = self.engagement_thresholds.get(source, {}).get('view_velocity_threshold', 100)
            return min(1.0, velocity / threshold)
            
        except Exception as e:
            self.logger.warning(f"Error calculating velocity for {item.get('id')}: {e}")
            return 0.5

    def _determine_trend_direction(self, item: Dict[str, Any], source: str) -> str:
        """Determine if content is trending up, down, or stable"""
        
        # Simplified logic - would need historical data for true trending
        engagement_rate = self._calculate_engagement_rate(item, source)
        velocity = self._calculate_velocity_score(item, source)
        
        if velocity > 0.7 and engagement_rate > 0.05:
            return 'up'
        elif velocity < 0.3:
            return 'down'
        else:
            return 'stable'

    def _calculate_trend_score(self, item: Dict[str, Any], source: str) -> float:
        """Calculate overall trend score for content"""
        
        engagement_rate = self._calculate_engagement_rate(item, source)
        velocity_score = self._calculate_velocity_score(item, source)
        virality_score = self._calculate_virality_score(item, source)
        
        # Weighted combination
        trend_score = (engagement_rate * 0.4 + velocity_score * 0.4 + virality_score * 0.2)
        return min(1.0, trend_score)

    def _classify_trend_type(self, item: Dict[str, Any], source: str) -> str:
        """Classify the type of trending behavior"""
        
        engagement_rate = self._calculate_engagement_rate(item, source)
        velocity_score = self._calculate_velocity_score(item, source)
        
        if engagement_rate > 0.08 and velocity_score > 0.8:
            return 'viral'
        elif velocity_score > 0.6:
            return 'steady_growth'
        elif engagement_rate > 0.05:
            return 'spike'
        else:
            return 'normal'