"""
Social Sentiment Analyzer - Advanced sentiment analysis for whale tracking

This module provides social sentiment analysis capabilities:
- Social media sentiment tracking
- News sentiment analysis
- Fear & Greed index monitoring
- Social momentum detection
- Sentiment-based whale correlation

Author: Pezhman Hajipour
Version: 2.7.4
"""

import logging
import asyncio
from typing import Dict, List, Optional, Tuple, Any
from datetime import datetime, timedelta
from dataclasses import dataclass, field
from collections import defaultdict, deque
import statistics
import re
import json
import requests
from concurrent.futures import ThreadPoolExecutor

from ..core_types import WhaleBotConfig, EnhancedTrade

logger = logging.getLogger(__name__)

@dataclass
class SentimentScore:
    """Sentiment score for an asset or market"""
    asset: str
    score: float  # -1.0 (very negative) to 1.0 (very positive)
    confidence: float  # 0.0 to 1.0
    sample_size: int  # Number of data points
    time_period: str  # "1H", "4H", "1D"
    sentiment_level: str  # "VERY_NEGATIVE", "NEGATIVE", "NEUTRAL", "POSITIVE", "VERY_POSITIVE"
    momentum: str  # "INCREASING", "DECREASING", "STABLE"

@dataclass
class SocialTrend:
    """Social media trend analysis"""
    topic: str
    mentions_count: int
    sentiment: float
    trend_direction: str  # "RISING", "FALLING", "PEAK", "VALLEY"
    influence_score: float  # 0.0 to 1.0
    time_period: str
    key_keywords: List[str]

@dataclass
class NewsSentiment:
    """News sentiment analysis"""
    headline: str
    sentiment_score: float
    source: str
    timestamp: datetime
    relevance_score: float
    whale_mentions: List[str]  # Whale addresses mentioned

@dataclass
class FearGreedIndex:
    """Fear & Greed index components"""
    index_value: int  # 0 to 100
    components: Dict[str, float]  # Individual component scores
    interpretation: str  # "EXTREME_FEAR", "FEAR", "NEUTRAL", "GREED", "EXTREME_GREED"
    change_24h: int  # 24-hour change
    whale_correlation: float  # Correlation with whale activity

@dataclass
class SentimentAnomaly:
    """Detected sentiment anomaly"""
    timestamp: datetime
    anomaly_type: str  # "SENTIMENT_SPIKE", "SENTIMENT_DIVERGENCE", "WHALE_SENTIMENT_MISMATCH"
    asset: str
    current_sentiment: float
    historical_average: float
    anomaly_score: float  # 0.0 to 1.0
    potential_causes: List[str]
    trading_implications: List[str]

class SocialSentimentAnalyzer:
    """
    Advanced social sentiment analysis system
    
    Features:
    - Multi-source sentiment aggregation
    - Social media trend detection
    - News sentiment analysis
    - Fear & Greed index monitoring
    - Whale sentiment correlation
    - Sentiment anomaly detection
    """
    
    def __init__(self, config: Optional[WhaleBotConfig] = None):
        """Initialize Social Sentiment Analyzer
        
        Args:
            config: Optional WhaleBotConfig, if not provided will use default
        """
        if config is None:
            config = WhaleBotConfig()
        
        self.config = config
        
        # Sentiment tracking
        self.sentiment_history: Dict[str, deque] = defaultdict(lambda: deque(maxlen=200))
        self.social_trends: List[SocialTrend] = []
        self.news_sentiment: List[NewsSentiment] = []
        self.fear_greed_history: deque = deque(maxlen=100)
        self.sentiment_anomalies: List[SentimentAnomaly] = []
        
        # Sentiment data sources (would integrate with real APIs)
        self.sentiment_sources = {
            "twitter": {"enabled": True, "weight": 0.4},
            "reddit": {"enabled": True, "weight": 0.3},
            "news": {"enabled": True, "weight": 0.3},
            "github": {"enabled": False, "weight": 0.1}
        }
        
        # Sentiment thresholds
        self.very_positive_threshold = 0.6
        self.positive_threshold = 0.2
        self.negative_threshold = -0.2
        self.very_negative_threshold = -0.6
        self.anomaly_threshold = 2.0  # Standard deviations
        
        # Keywords for sentiment analysis
        self.positive_keywords = [
            "bull", "moon", "pump", "hodl", "diamond", "rocket", "buy", "long",
            "bullish", "breakout", "rally", "surge", "gains", "profit", "up",
            "strong", "support", "adoption", "partnership", "upgrade"
        ]
        
        self.negative_keywords = [
            "bear", "dump", "crash", "sell", "short", "bearish", "correction",
            "decline", "drop", "loss", "panic", "fear", "selloff", "resistance",
            "rejection", "weak", "hack", "regulation", "ban", "concern"
        ]
        
        # Whale-specific keywords
        self.whale_keywords = [
            "whale", "whales", "big", "large", "institutional", "smart money",
            "accumulation", "distribution", "wall", "buy wall", "sell wall"
        ]
        
        logger.info(f"SocialSentimentAnalyzer initialized with {len(self.sentiment_sources)} sources")
    
    async def analyze_asset_sentiment(self, asset: str, timeframe: str = "1H") -> SentimentScore:
        """
        Analyze overall sentiment for an asset
        
        Args:
            asset: Asset symbol (e.g., "BTC", "ETH")
            timeframe: Analysis timeframe
            
        Returns:
            SentimentScore with comprehensive sentiment analysis
        """
        try:
            # Get sentiment data from multiple sources
            source_sentiments = await self._aggregate_source_sentiments(asset, timeframe)
            
            if not source_sentiments:
                return SentimentScore(
                    asset=asset,
                    score=0.0,
                    confidence=0.0,
                    sample_size=0,
                    time_period=timeframe,
                    sentiment_level="NEUTRAL",
                    momentum="STABLE"
                )
            
            # Calculate weighted average sentiment
            weighted_sentiment = self._calculate_weighted_sentiment(source_sentiments)
            
            # Calculate confidence
            confidence = self._calculate_sentiment_confidence(source_sentiments)
            
            # Determine sentiment level
            sentiment_level = self._classify_sentiment_level(weighted_sentiment)
            
            # Analyze momentum
            momentum = self._analyze_sentiment_momentum(asset, timeframe)
            
            # Store sentiment data
            self.sentiment_history[f"{asset}_{timeframe}"].append({
                'timestamp': datetime.now(),
                'sentiment': weighted_sentiment,
                'confidence': confidence
            })
            
            # Check for anomalies
            await self._check_sentiment_anomalies(asset, weighted_sentiment, timeframe)
            
            return SentimentScore(
                asset=asset,
                score=weighted_sentiment,
                confidence=confidence,
                sample_size=sum(s['sample_size'] for s in source_sentiments),
                time_period=timeframe,
                sentiment_level=sentiment_level,
                momentum=momentum
            )
            
        except Exception as e:
            logger.error(f"Error analyzing sentiment for {asset}: {e}")
            return SentimentScore(
                asset=asset,
                score=0.0,
                confidence=0.0,
                sample_size=0,
                time_period=timeframe,
                sentiment_level="NEUTRAL",
                momentum="STABLE"
            )
    
    async def detect_social_trends(self, timeframe: str = "4H") -> List[SocialTrend]:
        """
        Detect trending topics in social media
        
        Args:
            timeframe: Analysis timeframe
            
        Returns:
            List of SocialTrend objects
        """
        try:
            # In a real implementation, this would fetch from social media APIs
            # For now, generate simulated trends
            
            trends = []
            trending_topics = [
                "Bitcoin ETF", "Ethereum 2.0", "DeFi Summer", "NFT Market",
                "Crypto Regulation", "Institutional Adoption", "Layer 2 Solutions"
            ]
            
            for topic in trending_topics:
                # Simulate trend analysis
                mentions_count = self._simulate_mentions_count(topic)
                sentiment = self._simulate_topic_sentiment(topic)
                
                trend = SocialTrend(
                    topic=topic,
                    mentions_count=mentions_count,
                    sentiment=sentiment,
                    trend_direction=self._determine_trend_direction(topic),
                    influence_score=self._calculate_influence_score(mentions_count, sentiment),
                    time_period=timeframe,
                    key_keywords=self._extract_keywords(topic)
                )
                
                trends.append(trend)
            
            # Sort by influence score
            trends.sort(key=lambda t: t.influence_score, reverse=True)
            
            # Store trending data
            self.social_trends.extend(trends)
            
            # Keep only recent trends
            if len(self.social_trends) > 100:
                self.social_trends = self.social_trends[-100:]
            
            return trends[:10]  # Return top 10 trends
            
        except Exception as e:
            logger.error(f"Error detecting social trends: {e}")
            return []
    
    async def analyze_news_sentiment(self, asset: str) -> List[NewsSentiment]:
        """
        Analyze news sentiment for an asset
        
        Args:
            asset: Asset symbol
            
        Returns:
            List of NewsSentiment objects
        """
        try:
            # Simulate news sentiment analysis
            # In real implementation, would fetch from news APIs
            
            news_headlines = [
                f"{asset} Reaches New All-Time High",
                f"Major {asset} Partnership Announced",
                f"{asset} Technical Analysis: Bullish Signals",
                f"Institutional Interest in {asset} Grows",
                f"{asset} Market Cap Milestone Reached"
            ]
            
            news_sentiments = []
            for headline in news_headlines:
                sentiment = self._analyze_headline_sentiment(headline)
                
                news_item = NewsSentiment(
                    headline=headline,
                    sentiment_score=sentiment,
                    source="CryptoNews",
                    timestamp=datetime.now(),
                    relevance_score=0.8,  # Simulated relevance
                    whale_mentions=self._extract_whale_mentions(headline)
                )
                
                news_sentiments.append(news_item)
            
            # Store news sentiment
            self.news_sentiment.extend(news_sentiments)
            
            # Keep only recent news
            cutoff_time = datetime.now() - timedelta(hours=24)
            self.news_sentiment = [n for n in self.news_sentiment if n.timestamp >= cutoff_time]
            
            return news_sentiments
            
        except Exception as e:
            logger.error(f"Error analyzing news sentiment for {asset}: {e}")
            return []
    
    async def calculate_fear_greed_index(self, asset: str) -> FearGreedIndex:
        """
        Calculate Fear & Greed index for an asset
        
        Args:
            asset: Asset symbol
            
        Returns:
            FearGreedIndex with components and interpretation
        """
        try:
            # Simulate Fear & Greed index components
            # In real implementation, would calculate from actual data
            
            components = {
                "volatility": 0.6,  # 30-day volatility
                "momentum": 0.7,    # 50-day momentum
                "social_media": 0.8,  # Social media sentiment
                "surveys": 0.5,     # Investor surveys
                "dominance": 0.9,   # Market dominance
                "trends": 0.6       # Search trends
            }
            
            # Calculate overall index
            index_value = int(sum(components.values()) * 100 / len(components))
            
            # Determine interpretation
            interpretation = self._interpret_fear_greed(index_value)
            
            # Calculate 24-hour change (simulated)
            change_24h = self._simulate_24h_change()
            
            # Calculate whale correlation
            whale_correlation = self._calculate_whale_sentiment_correlation(asset)
            
            index = FearGreedIndex(
                index_value=index_value,
                components=components,
                interpretation=interpretation,
                change_24h=change_24h,
                whale_correlation=whale_correlation
            )
            
            # Store history
            self.fear_greed_history.append({
                'timestamp': datetime.now(),
                'value': index_value,
                'asset': asset
            })
            
            return index
            
        except Exception as e:
            logger.error(f"Error calculating Fear & Greed index for {asset}: {e}")
            return FearGreedIndex(
                index_value=50,
                components={"error": 0.5},
                interpretation="NEUTRAL",
                change_24h=0,
                whale_correlation=0.0
            )
    
    async def correlate_whale_sentiment(self, whale_address: str, asset: str) -> Dict[str, Any]:
        """
        Correlate whale activity with social sentiment
        
        Args:
            whale_address: Whale wallet address
            asset: Asset symbol
            
        Returns:
            Dictionary with correlation analysis
        """
        try:
            # Get recent sentiment data
            sentiment_key = f"{asset}_1H"
            recent_sentiment = list(self.sentiment_history[sentiment_key])[-10:]
            
            # Simulate whale activity correlation
            # In real implementation, would analyze actual whale trading vs sentiment
            
            correlation_analysis = {
                "whale_address": whale_address,
                "asset": asset,
                "sentiment_correlation": self._simulate_sentiment_correlation(),
                "leading_indicator": self._determine_leading_indicator(),
                "sentiment_accuracy": 0.75,  # How well sentiment predicts whale moves
                "recent_activity": {
                    "trades_count": 5,
                    "avg_size": 2500000,  # $2.5M
                    "sentiment_at_trade": 0.3
                },
                "recommendations": [
                    "Monitor sentiment for entry signals",
                    "High sentiment + whale buying = strong signal",
                    "Low sentiment + whale selling = contrarian signal"
                ]
            }
            
            return correlation_analysis
            
        except Exception as e:
            logger.error(f"Error correlating whale sentiment for {whale_address}: {e}")
            return {}
    
    async def _aggregate_source_sentiments(self, asset: str, timeframe: str) -> List[Dict[str, Any]]:
        """Aggregate sentiment from multiple sources"""
        source_sentiments = []
        
        for source, config in self.sentiment_sources.items():
            if not config["enabled"]:
                continue
            
            # Simulate source sentiment
            sentiment_data = self._simulate_source_sentiment(source, asset, timeframe)
            source_sentiments.append(sentiment_data)
        
        return source_sentiments
    
    def _calculate_weighted_sentiment(self, source_sentiments: List[Dict[str, Any]]) -> float:
        """Calculate weighted average sentiment"""
        if not source_sentiments:
            return 0.0
        
        weighted_sum = 0.0
        total_weight = 0.0
        
        for data in source_sentiments:
            source = data["source"]
            weight = self.sentiment_sources[source]["weight"]
            sentiment = data["sentiment"]
            confidence = data["confidence"]
            
            # Apply confidence weighting
            adjusted_weight = weight * confidence
            weighted_sum += sentiment * adjusted_weight
            total_weight += adjusted_weight
        
        return weighted_sum / total_weight if total_weight > 0 else 0.0
    
    def _calculate_sentiment_confidence(self, source_sentiments: List[Dict[str, Any]]) -> float:
        """Calculate confidence in sentiment analysis"""
        if not source_sentiments:
            return 0.0
        
        # Base confidence on number of sources
        source_count = len(source_sentiments)
        source_factor = min(1.0, source_count / 3.0)  # Full confidence with 3+ sources
        
        # Confidence from individual source confidence
        avg_confidence = statistics.mean([s["confidence"] for s in source_sentiments])
        
        # Sample size confidence
        total_samples = sum(s["sample_size"] for s in source_sentiments)
        sample_factor = min(1.0, total_samples / 100.0)  # Full confidence with 100+ samples
        
        return (source_factor + avg_confidence + sample_factor) / 3
    
    def _classify_sentiment_level(self, sentiment_score: float) -> str:
        """Classify sentiment level from score"""
        if sentiment_score >= self.very_positive_threshold:
            return "VERY_POSITIVE"
        elif sentiment_score >= self.positive_threshold:
            return "POSITIVE"
        elif sentiment_score <= self.very_negative_threshold:
            return "VERY_NEGATIVE"
        elif sentiment_score <= self.negative_threshold:
            return "NEGATIVE"
        else:
            return "NEUTRAL"
    
    def _analyze_sentiment_momentum(self, asset: str, timeframe: str) -> str:
        """Analyze sentiment momentum"""
        sentiment_key = f"{asset}_{timeframe}"
        history = list(self.sentiment_history[sentiment_key])
        
        if len(history) < 5:
            return "STABLE"
        
        # Compare recent average to older average
        recent_avg = statistics.mean([h['sentiment'] for h in history[-3:]])
        older_avg = statistics.mean([h['sentiment'] for h in history[-6:-3]])
        
        difference = recent_avg - older_avg
        
        if difference > 0.2:
            return "INCREASING"
        elif difference < -0.2:
            return "DECREASING"
        else:
            return "STABLE"
    
    async def _check_sentiment_anomalies(self, asset: str, current_sentiment: float, timeframe: str):
        """Check for sentiment anomalies"""
        try:
            sentiment_key = f"{asset}_{timeframe}"
            history = list(self.sentiment_history[sentiment_key])
            
            if len(history) < 10:
                return
            
            # Calculate historical statistics
            historical_sentiments = [h['sentiment'] for h in history[-20:]]
            mean_sentiment = statistics.mean(historical_sentiments)
            std_sentiment = statistics.stdev(historical_sentiments) if len(historical_sentiments) > 1 else 0.0
            
            # Check for anomalies
            if std_sentiment > 0:
                z_score = abs(current_sentiment - mean_sentiment) / std_sentiment
                
                if z_score > self.anomaly_threshold:
                    anomaly = SentimentAnomaly(
                        timestamp=datetime.now(),
                        anomaly_type="SENTIMENT_SPIKE",
                        asset=asset,
                        current_sentiment=current_sentiment,
                        historical_average=mean_sentiment,
                        anomaly_score=z_score / self.anomaly_threshold,
                        potential_causes=["news_event", "whale_activity", "market_movement"],
                        trading_implications=["wait_for_confirmation", "monitor_for_reversal"]
                    )
                    
                    self.sentiment_anomalies.append(anomaly)
                    logger.info(f"Sentiment anomaly detected for {asset}: {current_sentiment:.2f}")
        
        except Exception as e:
            logger.error(f"Error checking sentiment anomalies for {asset}: {e}")
    
    def _simulate_source_sentiment(self, source: str, asset: str, timeframe: str) -> Dict[str, Any]:
        """Simulate sentiment data from a source"""
        # In real implementation, would fetch from actual APIs
        import random
        
        return {
            "source": source,
            "sentiment": random.uniform(-0.8, 0.8),
            "confidence": random.uniform(0.5, 0.9),
            "sample_size": random.randint(50, 500)
        }
    
    def _simulate_mentions_count(self, topic: str) -> int:
        """Simulate mention count for a topic"""
        import random
        return random.randint(100, 10000)
    
    def _simulate_topic_sentiment(self, topic: str) -> float:
        """Simulate sentiment for a topic"""
        import random
        return random.uniform(-0.5, 0.7)
    
    def _determine_trend_direction(self, topic: str) -> str:
        """Determine trend direction for a topic"""
        import random
        directions = ["RISING", "FALLING", "PEAK", "VALLEY"]
        return random.choice(directions)
    
    def _calculate_influence_score(self, mentions: int, sentiment: float) -> float:
        """Calculate influence score for a trend"""
        # Combine mentions and sentiment
        mention_factor = min(1.0, mentions / 1000.0)
        sentiment_factor = abs(sentiment)
        return (mention_factor + sentiment_factor) / 2
    
    def _extract_keywords(self, topic: str) -> List[str]:
        """Extract key keywords from topic"""
        return topic.lower().split()
    
    def _analyze_headline_sentiment(self, headline: str) -> float:
        """Analyze sentiment of a news headline"""
        words = re.findall(r'\b\w+\b', headline.lower())
        
        positive_count = sum(1 for word in words if word in self.positive_keywords)
        negative_count = sum(1 for word in words if word in self.negative_keywords)
        
        if positive_count + negative_count == 0:
            return 0.0
        
        sentiment = (positive_count - negative_count) / (positive_count + negative_count)
        return max(-1.0, min(1.0, sentiment))
    
    def _extract_whale_mentions(self, text: str) -> List[str]:
        """Extract whale-related mentions from text"""
        words = re.findall(r'\b\w+\b', text.lower())
        return [word for word in words if word in self.whale_keywords]
    
    def _interpret_fear_greed(self, index_value: int) -> str:
        """Interpret Fear & Greed index value"""
        if index_value <= 25:
            return "EXTREME_FEAR"
        elif index_value <= 45:
            return "FEAR"
        elif index_value <= 55:
            return "NEUTRAL"
        elif index_value <= 75:
            return "GREED"
        else:
            return "EXTREME_GREED"
    
    def _simulate_24h_change(self) -> int:
        """Simulate 24-hour change in Fear & Greed index"""
        import random
        return random.randint(-10, 10)
    
    def _calculate_whale_sentiment_correlation(self, asset: str) -> float:
        """Calculate correlation between whale activity and sentiment"""
        # Simulated correlation
        import random
        return random.uniform(-0.3, 0.7)
    
    def _simulate_sentiment_correlation(self) -> float:
        """Simulate sentiment correlation with whale activity"""
        import random
        return random.uniform(-0.5, 0.8)
    
    def _determine_leading_indicator(self) -> str:
        """Determine which sentiment indicator leads whale activity"""
        indicators = ["social_media", "news", "fear_greed", "trends"]
        import random
        return random.choice(indicators)
    
    def get_sentiment_summary(self, hours_back: int = 24) -> Dict[str, Any]:
        """Get comprehensive sentiment summary"""
        cutoff_time = datetime.now() - timedelta(hours=hours_back)
        
        # Calculate overall market sentiment
        all_sentiments = []
        for sentiment_data in self.sentiment_history.values():
            recent_data = [s for s in sentiment_data if s['timestamp'] >= cutoff_time]
            if recent_data:
                all_sentiments.extend([s['sentiment'] for s in recent_data])
        
        avg_sentiment = statistics.mean(all_sentiments) if all_sentiments else 0.0
        
        # Count sentiment anomalies
        recent_anomalies = [a for a in self.sentiment_anomalies if a.timestamp >= cutoff_time]
        
        # Fear & Greed trend
        fear_greed_trend = "STABLE"
        if len(self.fear_greed_history) >= 2:
            recent_fgi = list(self.fear_greed_history)[-5:]
            if recent_fgi[-1]['value'] > recent_fgi[0]['value']:
                fear_greed_trend = "INCREASING"
            elif recent_fgi[-1]['value'] < recent_fgi[0]['value']:
                fear_greed_trend = "DECREASING"
        
        return {
            "overall_sentiment": avg_sentiment,
            "sentiment_level": self._classify_sentiment_level(avg_sentiment),
            "fear_greed_index": list(self.fear_greed_history)[-1]['value'] if self.fear_greed_history else 50,
            "fear_greed_trend": fear_greed_trend,
            "sentiment_anomalies": len(recent_anomalies),
            "active_trends": len([t for t in self.social_trends if t.influence_score > 0.5]),
            "news_sentiment": len(self.news_sentiment),
            "data_sources_active": sum(1 for s in self.sentiment_sources.values() if s["enabled"]),
            "whale_sentiment_correlation": self._calculate_whale_sentiment_correlation("BTC"),
            "top_trending_topics": [t.topic for t in self.social_trends[-5:]],
            "sentiment_confidence": 0.8 if all_sentiments else 0.0
        }
    
    def reset_sentiment_data(self):
        """Reset all sentiment analysis data"""
        self.sentiment_history.clear()
        self.social_trends.clear()
        self.news_sentiment.clear()
        self.fear_greed_history.clear()
        self.sentiment_anomalies.clear()
        
        logger.info("Sentiment analysis data reset")

# Alias for backward compatibility
SentimentAnalyzer = SocialSentimentAnalyzer