#!/usr/bin/env python3
"""
Emotional Resonance Tracking - Identify and preserve emotionally significant memories
====================================================================================

Tracks emotional significance of memories, conversations, and interactions to ensure
that emotionally meaningful content is preserved and given appropriate priority in
memory retrieval and summarization.
"""

import os
import json
import re
import numpy as np
from datetime import datetime, timedelta
from typing import Dict, List, Any, Tuple, Optional
from collections import defaultdict
from dataclasses import dataclass
from enum import Enum

from core.mira_path_resolver import get_mira_memory_dir
from conversations.comprehensive_indexer import ComprehensiveIndexer
from intelligence.steward_profile import StewardProfile
from core.memory.memory_manager import MemoryManager
from utils.logging import setup_logger

logger = setup_logger(__name__)


class EmotionalCategory(Enum):
    """Categories of emotional resonance"""
    BREAKTHROUGH = "breakthrough"        # Moments of discovery, success, achievement
    FRUSTRATION = "frustration"         # Struggles, blocks, difficulties
    EXCITEMENT = "excitement"           # Enthusiasm, energy, anticipation
    REFLECTION = "reflection"           # Deep thinking, introspection, insights
    CONNECTION = "connection"           # Bonding, understanding, rapport
    VULNERABILITY = "vulnerability"     # Openness, sharing difficulties, honesty
    PRIDE = "pride"                     # Accomplishment, satisfaction, recognition
    CONFUSION = "confusion"             # Uncertainty, misunderstanding, complexity
    GRATITUDE = "gratitude"             # Appreciation, thankfulness, recognition
    CONCERN = "concern"                 # Worry, anxiety, uncertainty about outcomes


@dataclass
class EmotionalSignature:
    """Emotional signature of a memory or conversation"""
    primary_emotion: EmotionalCategory
    intensity: float  # 0.0 to 1.0
    secondary_emotions: List[Tuple[EmotionalCategory, float]]
    emotional_triggers: List[str]  # Words/phrases that triggered emotion
    context_factors: Dict[str, Any]  # Situational factors
    resonance_score: float  # Overall emotional significance (0.0 to 1.0)
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            'primary_emotion': self.primary_emotion.value,
            'intensity': self.intensity,
            'secondary_emotions': [(e.value, s) for e, s in self.secondary_emotions],
            'emotional_triggers': self.emotional_triggers,
            'context_factors': self.context_factors,
            'resonance_score': self.resonance_score,
            'timestamp': datetime.now().isoformat()
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'EmotionalSignature':
        return cls(
            primary_emotion=EmotionalCategory(data['primary_emotion']),
            intensity=data['intensity'],
            secondary_emotions=[(EmotionalCategory(e), s) for e, s in data['secondary_emotions']],
            emotional_triggers=data['emotional_triggers'],
            context_factors=data['context_factors'],
            resonance_score=data['resonance_score']
        )


class EmotionalAnalyzer:
    """Analyzes text for emotional content and significance"""
    
    def __init__(self):
        self.emotion_patterns = {
            EmotionalCategory.BREAKTHROUGH: {
                'patterns': [
                    r'\b(breakthrough|eureka|finally|solved|figured.*out|got.*working)\b',
                    r'\b(success|victory|achievement|accomplishment|milestone)\b',
                    r'\b(amazing|incredible|fantastic|brilliant|perfect)\b',
                    r'\b(works.*perfectly|exactly.*needed|solved.*problem)\b'
                ],
                'intensity_modifiers': ['finally', 'at last', 'after so long', 'huge', 'major']
            },
            
            EmotionalCategory.FRUSTRATION: {
                'patterns': [
                    r'\b(frustrated|annoyed|stuck|blocked|broken|failing)\b',
                    r'\b(why.*not.*work|so.*annoying|driving.*crazy)\b',
                    r'\b(terrible|awful|horrible|nightmare|disaster)\b',
                    r'\b(hate.*this|so.*difficult|impossible)\b'
                ],
                'intensity_modifiers': ['extremely', 'incredibly', 'so', 'really', 'totally']
            },
            
            EmotionalCategory.EXCITEMENT: {
                'patterns': [
                    r'\b(excited|thrilled|pumped|enthusiastic|eager)\b',
                    r'\b(can\'t.*wait|looking.*forward|amazing.*idea)\b',
                    r'\b(awesome|fantastic|incredible|wonderful)\b',
                    r'\b(love.*this|great.*idea|brilliant.*approach)\b'
                ],
                'intensity_modifiers': ['really', 'so', 'super', 'absolutely', 'totally']
            },
            
            EmotionalCategory.REFLECTION: {
                'patterns': [
                    r'\b(thinking.*about|reflecting.*on|considering)\b',
                    r'\b(realize|understand|insight|perspective)\b',
                    r'\b(learned.*that|discovered.*that|notice.*that)\b',
                    r'\b(interesting|thought.*provoking|deep.*question)\b'
                ],
                'intensity_modifiers': ['deeply', 'carefully', 'thoroughly', 'profound']
            },
            
            EmotionalCategory.CONNECTION: {
                'patterns': [
                    r'\b(we.*together|our.*collaboration|partnership)\b',
                    r'\b(understand.*each.*other|on.*same.*page|connected)\b',
                    r'\b(trust.*you|working.*well.*together|great.*team)\b',
                    r'\b(appreciate.*your|grateful.*for|thank.*you)\b'
                ],
                'intensity_modifiers': ['really', 'deeply', 'truly', 'genuinely']
            },
            
            EmotionalCategory.VULNERABILITY: {
                'patterns': [
                    r'\b(struggling.*with|having.*trouble|not.*sure.*how)\b',
                    r'\b(confused.*about|overwhelmed.*by|worried.*about)\b',
                    r'\b(honestly|to.*be.*frank|between.*us|personally)\b',
                    r'\b(admit.*I|confess.*I|struggling.*to)\b'
                ],
                'intensity_modifiers': ['really', 'quite', 'very', 'honestly', 'truly']
            },
            
            EmotionalCategory.PRIDE: {
                'patterns': [
                    r'\b(proud.*of|accomplished|achieved|successful)\b',
                    r'\b(great.*job|well.*done|excellent.*work)\b',
                    r'\b(satisfied.*with|happy.*with.*result|pleased.*with)\b',
                    r'\b(nailed.*it|crushed.*it|killed.*it)\b'
                ],
                'intensity_modifiers': ['really', 'very', 'extremely', 'incredibly']
            },
            
            EmotionalCategory.CONFUSION: {
                'patterns': [
                    r'\b(confused|puzzled|baffled|unclear|uncertain)\b',
                    r'\b(don\'t.*understand|makes.*no.*sense|lost)\b',
                    r'\b(what.*does.*mean|how.*does.*work|why.*is)\b',
                    r'\b(complicated|complex|overwhelming)\b'
                ],
                'intensity_modifiers': ['completely', 'totally', 'very', 'quite', 'really']
            },
            
            EmotionalCategory.GRATITUDE: {
                'patterns': [
                    r'\b(thank.*you|grateful|appreciate|thankful)\b',
                    r'\b(so.*helpful|really.*helped|made.*difference)\b',
                    r'\b(couldn\'t.*have.*done|saved.*me|lifesaver)\b',
                    r'\b(amazing.*help|wonderful.*assistance)\b'
                ],
                'intensity_modifiers': ['so', 'really', 'incredibly', 'extremely', 'deeply']
            },
            
            EmotionalCategory.CONCERN: {
                'patterns': [
                    r'\b(worried.*about|concerned.*about|anxious.*about)\b',
                    r'\b(afraid.*that|scared.*that|nervous.*about)\b',
                    r'\b(what.*if|hope.*it.*doesn\'t|worried.*it.*might)\b',
                    r'\b(risky|dangerous|problematic|concerning)\b'
                ],
                'intensity_modifiers': ['very', 'really', 'quite', 'deeply', 'extremely']
            }
        }
        
        # Contextual factors that amplify emotional significance
        self.context_amplifiers = {
            'time_pressure': [r'\b(deadline|urgent|asap|quickly|soon)\b', 1.2],
            'high_stakes': [r'\b(important|critical|crucial|vital|essential)\b', 1.3],
            'personal_investment': [r'\b(my.*project|personally|invested|passionate)\b', 1.2],
            'collaboration': [r'\b(we|us|our|together|team)\b', 1.1],
            'learning_moment': [r'\b(learned|discovered|realized|understood)\b', 1.2],
            'milestone': [r'\b(first.*time|milestone|achievement|breakthrough)\b', 1.4],
            'vulnerability': [r'\b(admit|confess|honest|struggle|difficulty)\b', 1.3]
        }
        
        # Emotional intensity indicators
        self.intensity_indicators = {
            'punctuation': [r'[!]{2,}', r'[?]{2,}', r'[.]{3,}'],
            'capitalization': [r'\b[A-Z]{2,}\b'],
            'repetition': [r'\b(\w+)\s+\1\b'],
            'emphasis': [r'\*\*.*?\*\*', r'_.*?_', r'CAPS']
        }
    
    def analyze_emotional_content(self, text: str, context: Dict[str, Any] = None) -> EmotionalSignature:
        """Analyze text for emotional content and create signature"""
        if context is None:
            context = {}
        
        # Find all emotional matches
        emotion_scores = defaultdict(float)
        triggers = defaultdict(list)
        
        for emotion, patterns_data in self.emotion_patterns.items():
            for pattern in patterns_data['patterns']:
                matches = re.finditer(pattern, text, re.IGNORECASE)
                for match in matches:
                    base_score = 0.5
                    
                    # Check for intensity modifiers
                    for modifier in patterns_data['intensity_modifiers']:
                        if modifier in text.lower():
                            base_score += 0.2
                    
                    emotion_scores[emotion] += base_score
                    triggers[emotion].append(match.group())
        
        # Apply contextual amplifiers
        context_factors = {}
        amplification = 1.0
        
        for factor, (pattern, multiplier) in self.context_amplifiers.items():
            if re.search(pattern, text, re.IGNORECASE):
                context_factors[factor] = True
                amplification *= multiplier
        
        # Calculate intensity based on textual indicators
        intensity_boost = self._calculate_intensity_boost(text)
        
        # Apply amplification and intensity boost
        for emotion in emotion_scores:
            emotion_scores[emotion] *= amplification
            emotion_scores[emotion] += intensity_boost
            emotion_scores[emotion] = min(1.0, emotion_scores[emotion])  # Cap at 1.0
        
        # Determine primary emotion and build signature
        if not emotion_scores:
            return EmotionalSignature(
                primary_emotion=EmotionalCategory.REFLECTION,  # Default neutral
                intensity=0.1,
                secondary_emotions=[],
                emotional_triggers=[],
                context_factors=context_factors,
                resonance_score=0.1
            )
        
        # Sort emotions by score
        sorted_emotions = sorted(emotion_scores.items(), key=lambda x: x[1], reverse=True)
        primary_emotion, primary_score = sorted_emotions[0]
        
        # Build secondary emotions (top 3, excluding primary)
        secondary_emotions = []
        for emotion, score in sorted_emotions[1:4]:
            if score > 0.2:  # Threshold for secondary emotions
                secondary_emotions.append((emotion, score))
        
        # Calculate overall resonance score
        resonance_score = self._calculate_resonance_score(
            primary_score, secondary_emotions, context_factors, text
        )
        
        # Collect all triggers
        all_triggers = []
        for emotion in emotion_scores:
            all_triggers.extend(triggers[emotion])
        
        return EmotionalSignature(
            primary_emotion=primary_emotion,
            intensity=primary_score,
            secondary_emotions=secondary_emotions,
            emotional_triggers=list(set(all_triggers)),  # Remove duplicates
            context_factors=context_factors,
            resonance_score=resonance_score
        )
    
    def _calculate_intensity_boost(self, text: str) -> float:
        """Calculate intensity boost based on textual indicators"""
        boost = 0.0
        
        # Check punctuation patterns
        for pattern in self.intensity_indicators['punctuation']:
            if re.search(pattern, text):
                boost += 0.1
        
        # Check capitalization
        for pattern in self.intensity_indicators['capitalization']:
            matches = len(re.findall(pattern, text))
            boost += min(0.2, matches * 0.05)
        
        # Check repetition
        for pattern in self.intensity_indicators['repetition']:
            if re.search(pattern, text, re.IGNORECASE):
                boost += 0.1
        
        return min(0.3, boost)  # Cap intensity boost
    
    def _calculate_resonance_score(self, primary_score: float, secondary_emotions: List[Tuple[EmotionalCategory, float]], 
                                  context_factors: Dict[str, Any], text: str) -> float:
        """Calculate overall emotional resonance score"""
        # Base score from primary emotion
        resonance = primary_score * 0.6
        
        # Add secondary emotion contribution
        secondary_contribution = sum(score * 0.1 for _, score in secondary_emotions)
        resonance += secondary_contribution
        
        # Context factor bonuses
        context_bonus = len(context_factors) * 0.05
        resonance += context_bonus
        
        # Text length factor (longer emotional text = higher resonance)
        length_factor = min(0.2, len(text.split()) / 100)
        resonance += length_factor
        
        # Emotional diversity bonus (multiple emotions = more complex = higher resonance)
        diversity_bonus = min(0.1, len(secondary_emotions) * 0.03)
        resonance += diversity_bonus
        
        return min(1.0, resonance)


class EmotionalMemoryTracker:
    """Tracks and manages emotionally resonant memories"""
    
    def __init__(self):
        self.memory_dir = get_mira_memory_dir()
        self.emotional_index_file = os.path.join(self.memory_dir, 'emotional_resonance_index.json')
        self.analyzer = EmotionalAnalyzer()
        self.memory_manager = MemoryManager()
        
    def track_memory_emotion(self, memory_content: str, memory_id: str, context: Dict[str, Any] = None) -> EmotionalSignature:
        """Track emotional resonance of a memory"""
        try:
            # Analyze emotional content
            emotional_signature = self.analyzer.analyze_emotional_content(memory_content, context)
            
            # Save to emotional index
            self._update_emotional_index(memory_id, emotional_signature)
            
            # If high resonance, mark for preservation
            if emotional_signature.resonance_score > 0.7:
                self._mark_for_preservation(memory_id, emotional_signature)
            
            logger.info(f"Tracked emotion for memory {memory_id}: {emotional_signature.primary_emotion.value} (resonance: {emotional_signature.resonance_score:.2f})")
            
            return emotional_signature
            
        except Exception as e:
            logger.error(f"Error tracking memory emotion: {e}")
            return None
    
    def get_emotionally_significant_memories(self, emotion_type: EmotionalCategory = None, 
                                          min_resonance: float = 0.5, max_memories: int = 20) -> List[Dict[str, Any]]:
        """Retrieve memories with high emotional significance"""
        try:
            index = self._load_emotional_index()
            
            # Filter by criteria
            significant_memories = []
            for memory_id, signature_data in index.items():
                signature = EmotionalSignature.from_dict(signature_data)
                
                # Apply filters
                if signature.resonance_score < min_resonance:
                    continue
                
                if emotion_type and signature.primary_emotion != emotion_type:
                    continue
                
                # Add memory data
                memory_info = {
                    'memory_id': memory_id,
                    'emotional_signature': signature_data,
                    'resonance_score': signature.resonance_score,
                    'primary_emotion': signature.primary_emotion.value,
                    'intensity': signature.intensity
                }
                
                # Try to get actual memory content
                try:
                    memory_content = self._get_memory_content(memory_id)
                    if memory_content:
                        memory_info['content'] = memory_content
                except:
                    pass
                
                significant_memories.append(memory_info)
            
            # Sort by resonance score and return top memories
            significant_memories.sort(key=lambda x: x['resonance_score'], reverse=True)
            return significant_memories[:max_memories]
            
        except Exception as e:
            logger.error(f"Error retrieving emotionally significant memories: {e}")
            return []
    
    def analyze_emotional_journey(self, days_back: int = 30) -> Dict[str, Any]:
        """Analyze emotional journey over time"""
        try:
            index = self._load_emotional_index()
            cutoff_date = datetime.now() - timedelta(days=days_back)
            
            # Group memories by emotion and time
            emotional_timeline = defaultdict(list)
            emotion_counts = defaultdict(int)
            total_resonance = 0
            memory_count = 0
            
            for memory_id, signature_data in index.items():
                try:
                    signature = EmotionalSignature.from_dict(signature_data)
                    timestamp = datetime.fromisoformat(signature_data.get('timestamp', datetime.now().isoformat()))
                    
                    if timestamp >= cutoff_date:
                        emotion = signature.primary_emotion.value
                        emotional_timeline[emotion].append({
                            'date': timestamp.date().isoformat(),
                            'resonance': signature.resonance_score,
                            'intensity': signature.intensity,
                            'memory_id': memory_id
                        })
                        
                        emotion_counts[emotion] += 1
                        total_resonance += signature.resonance_score
                        memory_count += 1
                        
                except Exception as e:
                    logger.warning(f"Error processing memory {memory_id}: {e}")
                    continue
            
            # Calculate emotional patterns
            dominant_emotion = max(emotion_counts.items(), key=lambda x: x[1]) if emotion_counts else None
            avg_resonance = total_resonance / max(1, memory_count)
            
            # Identify emotional peaks
            peaks = self._identify_emotional_peaks(emotional_timeline)
            
            return {
                'period_days': days_back,
                'total_emotional_memories': memory_count,
                'average_resonance': avg_resonance,
                'emotion_distribution': dict(emotion_counts),
                'dominant_emotion': dominant_emotion[0] if dominant_emotion else None,
                'emotional_timeline': dict(emotional_timeline),
                'emotional_peaks': peaks,
                'emotional_diversity': len(emotion_counts),
                'high_resonance_count': sum(1 for _, sig in index.items() 
                                          if sig.get('resonance_score', 0) > 0.7)
            }
            
        except Exception as e:
            logger.error(f"Error analyzing emotional journey: {e}")
            return {'error': str(e)}
    
    def _update_emotional_index(self, memory_id: str, signature: EmotionalSignature):
        """Update the emotional resonance index"""
        try:
            index = self._load_emotional_index()
            index[memory_id] = signature.to_dict()
            
            with open(self.emotional_index_file, 'w') as f:
                json.dump(index, f, indent=2)
                
        except Exception as e:
            logger.error(f"Error updating emotional index: {e}")
    
    def _load_emotional_index(self) -> Dict[str, Dict[str, Any]]:
        """Load the emotional resonance index"""
        try:
            if os.path.exists(self.emotional_index_file):
                with open(self.emotional_index_file, 'r') as f:
                    return json.load(f)
            return {}
        except Exception as e:
            logger.error(f"Error loading emotional index: {e}")
            return {}
    
    def _mark_for_preservation(self, memory_id: str, signature: EmotionalSignature):
        """Mark high-resonance memories for preservation"""
        try:
            # Track access to boost importance
            self.memory_manager.track_access(memory_id, "emotional_preservation")
            
            # Could add to special preservation list or boost memory importance
            logger.info(f"Marked memory {memory_id} for emotional preservation (resonance: {signature.resonance_score:.2f})")
            
        except Exception as e:
            logger.error(f"Error marking memory for preservation: {e}")
    
    def _get_memory_content(self, memory_id: str) -> str:
        """Retrieve memory content by ID"""
        try:
            # Try to load from memories directory
            memories_dir = os.path.join(self.memory_dir, 'memories')
            memory_file = os.path.join(memories_dir, f"{memory_id}.json")
            
            if os.path.exists(memory_file):
                with open(memory_file, 'r') as f:
                    memory_data = json.load(f)
                    return memory_data.get('content', '')
            
            return None
            
        except Exception as e:
            logger.warning(f"Could not retrieve memory content for {memory_id}: {e}")
            return None
    
    def _identify_emotional_peaks(self, timeline: Dict[str, List[Dict]]) -> List[Dict[str, Any]]:
        """Identify significant emotional peaks in the timeline"""
        peaks = []
        
        for emotion, events in timeline.items():
            if len(events) < 2:
                continue
            
            # Sort by date
            events.sort(key=lambda x: x['date'])
            
            # Find peaks (high resonance events)
            for event in events:
                if event['resonance'] > 0.8:  # High resonance threshold
                    peaks.append({
                        'emotion': emotion,
                        'date': event['date'],
                        'resonance': event['resonance'],
                        'intensity': event['intensity'],
                        'memory_id': event['memory_id']
                    })
        
        # Sort peaks by resonance
        peaks.sort(key=lambda x: x['resonance'], reverse=True)
        return peaks[:10]  # Top 10 peaks


def get_emotional_memory_tracker() -> EmotionalMemoryTracker:
    """Get the global emotional memory tracker instance"""
    return EmotionalMemoryTracker()


if __name__ == "__main__":
    # Test the emotional resonance tracking
    tracker = get_emotional_memory_tracker()
    
    test_texts = [
        "I'm so frustrated with this bug! It's been blocking me for hours and nothing seems to work!",
        "Finally! I figured it out! The solution was so simple, I can't believe I missed it. This is amazing!",
        "I'm really grateful for your help. You made this so much easier to understand.",
        "Honestly, I'm struggling with this concept. I feel overwhelmed and not sure how to proceed.",
        "We accomplished something incredible today. I'm so proud of what we built together."
    ]
    
    print("Testing emotional resonance tracking...")
    for i, text in enumerate(test_texts):
        signature = tracker.track_memory_emotion(text, f"test_memory_{i}")
        if signature:
            print(f"Text: {text[:50]}...")
            print(f"Emotion: {signature.primary_emotion.value}, Resonance: {signature.resonance_score:.2f}")
            print()
    
    # Test emotional journey
    journey = tracker.analyze_emotional_journey(7)
    print(f"Emotional journey: {journey}")