#!/usr/bin/env python3
"""
Unified Intelligence Orchestrator
=================================

This module provides the master orchestration layer for all intelligence capabilities
in the MIRA memory system. It coordinates multiple AI subsystems to create a unified,
intelligent memory experience that enhances Claude's capabilities over time.

Purpose:
    - Orchestrate multiple intelligence engines
    - Coordinate memory, learning, and prediction systems
    - Provide unified interface for all AI capabilities
    - Enable emergent intelligence through system integration
    - Memory-focused intelligent decision making

Architecture:
    - UnifiedIntelligenceOrchestrator: Master coordination class
    - IntelligenceContext: Cross-system context sharing
    - Integration with auto-intelligence, lightning vidmem, recovery systems
    - Session-based intelligence accumulation
    - Performance metrics and recommendations

Key Features:
    - Multi-system AI coordination
    - Context-aware intelligence sharing
    - Predictive recommendation engine
    - Performance monitoring and optimization
    - Session insight accumulation
    - Recovery and resilience systems
    - Memory-enhanced learning

Usage:
    ```python
    from intelligence.unified_intelligence import UnifiedIntelligenceOrchestrator
    
    # Initialize orchestrator
    orchestrator = UnifiedIntelligenceOrchestrator()
    
    # Start intelligence session
    context = orchestrator.start_intelligence_session()
    
    # Process with intelligence
    result = orchestrator.process_with_intelligence(
        "Analyze memory patterns",
        context
    )
    
    # Get recommendations
    recommendations = context.predictive_recommendations
    ```

Integrated Systems:
    - AutoIntelligenceEngine: Automated learning and adaptation
    - LightningMemvidEngine: Ultra-fast memory video processing
    - IntelligentRecoveryEngine: Error recovery and resilience
    - Memory systems: Core storage and retrieval

Intelligence Features:
    - Cross-system learning
    - Predictive analytics
    - Performance optimization
    - Context preservation
    - Emergent behavior detection
    - Resource management

Author: MIRA Memory System
Version: 2.1 (Enhanced Documentation)
"""

import os
import sys
import json
import time
import asyncio
import threading
from datetime import datetime, timedelta
from pathlib import Path
from typing import Dict, List, Any, Optional, Union, Callable
from dataclasses import dataclass

# Import centralized config
sys.path.insert(0, str(Path(__file__).parent.parent))
from config import MEMORY_DIR
from contextlib import contextmanager

# Import all our enhanced systems
try:
    from .auto_intelligence import AutoIntelligenceEngine
    from ..core.engine.lightning_vidmem import LightningVidmem as LightningMemvidEngine 
    from ..security.intelligent_recovery import IntelligentRecoveryEngine, safe_execute
    AUTO_INTELLIGENCE_AVAILABLE = True
except ImportError as e:
    # print(f"⚠️ Some intelligence components not available: {e}")
    pass
    AUTO_INTELLIGENCE_AVAILABLE = False

@dataclass
class IntelligenceContext:
    """Context object that carries intelligence across operations"""
    memory_enhanced: bool
    auto_intelligence_active: bool
    lightning_memvid_active: bool
    recovery_system_active: bool
    session_insights: List[str]
    performance_metrics: Dict[str, float]
    predictive_recommendations: List[str]

class UnifiedIntelligenceOrchestrator:
    """
    The master orchestrator that makes Claude genuinely intelligent by
    seamlessly integrating all memory and intelligence capabilities.
    """
    
    def __init__(self):
        self.base_path = Path(str(MEMORY_DIR))
        self.project_root = Path(os.getcwd())
        
        # Core intelligence systems
        self.auto_intelligence = None
        self.lightning_memvid = None
        self.recovery_engine = None
        
        # State tracking
        self.session_start = datetime.now()
        self.intelligence_context = None
        self.background_processes = []
        self.performance_history = []
        
        # Initialize all systems
        self._initialize_intelligence_systems()
    
    def _initialize_intelligence_systems(self):
        """
        Initialize all intelligence subsystems with graceful degradation.
        No manual activation needed - everything works automatically.
        """
        try:
            # Auto-Intelligence Engine
            self.auto_intelligence = safe_execute(AutoIntelligenceEngine)
            if isinstance(self.auto_intelligence, dict) and self.auto_intelligence.get('error'):
                print("⚠️ Auto-intelligence initialization warning")
                self.auto_intelligence = None
            
            # Lightning Memvid Engine
            self.lightning_memvid = safe_execute(LightningMemvidEngine)
            if isinstance(self.lightning_memvid, dict) and self.lightning_memvid.get('error'):
                print("⚠️ Lightning memvid initialization failed")
                self.lightning_memvid = None
            
            # Generate initial intelligence context
            self.intelligence_context = self._generate_intelligence_context()
            
            # Start background intelligence processes
            self._start_background_intelligence()
            
            # print("🧠 Unified Intelligence System: ONLINE")
            
        except Exception as e:
            # print(f"⚠️ Unified intelligence initialization error: {e}")
            pass
            # Graceful degradation - basic functionality still available
    
    def _generate_intelligence_context(self) -> IntelligenceContext:
        """Generate comprehensive intelligence context for the session"""
        context = IntelligenceContext(
            memory_enhanced=False,
            auto_intelligence_active=False,
            lightning_memvid_active=False,
            recovery_system_active=False,
            session_insights=[],
            performance_metrics={},
            predictive_recommendations=[]
        )
        
        # Check auto-intelligence status
        if self.auto_intelligence:
            try:
                auto_context = self.auto_intelligence.get_context()
                context.auto_intelligence_active = auto_context.get('enhanced', False)
                context.memory_enhanced = auto_context.get('memory_available', False)
                context.session_insights.extend(auto_context.get('startup_insights', []))
            except:
                pass
        
        # Check recovery system
        if self.recovery_engine:
            try:
                health_status = self.recovery_engine.get_system_health()
                context.recovery_system_active = health_status.get('overall_health') == 'healthy'
            except:
                pass
        
        # Check lightning memvid
        if self.lightning_memvid:
            try:
                context.lightning_memvid_active = True
                # Add instant memory capabilities
                context.session_insights.append("Lightning-fast memory storage active")
            except:
                pass
        
        return context
    
    def process(self, context: Union[str, Dict[str, Any]], **kwargs) -> Dict[str, Any]:
        """
        Process any context with unified intelligence.
        This is the main entry point that orchestrates all capabilities.
        
        Args:
            context: The context to process (string or structured data)
            **kwargs: Additional options like include_memory, include_predictions, etc.
        
        Returns:
            Comprehensive analysis with all intelligence applied
        """
        start_time = time.time()
        
        # Convert string context to structured format
        if isinstance(context, str):
            context = {'query': context, 'timestamp': datetime.now().isoformat()}
        
        # Initialize comprehensive analysis result
        comprehensive_analysis = {
            'context': context,
            'timestamp': datetime.now().isoformat(),
            'session_context': self.intelligence_context.__dict__ if self.intelligence_context else {},
            'analysis_components': {},
            'unified_insights': [],
            'recommendations': [],
            'predictions': [],
            'confidence_score': 0.5,
            'processing_time': 0,
            'capabilities_used': [],
            'memory_enhanced': False,
            'auto_enhanced': False
        }
        
        # Extract options
        include_memory = kwargs.get('include_memory', True)
        include_predictions = kwargs.get('include_predictions', True)
        include_recovery = kwargs.get('include_recovery', True)
        
        try:
            # 1. Auto-Intelligence Enhancement
            if self.auto_intelligence:
                auto_analysis = safe_execute(
                    self.auto_intelligence.enhance_analysis, 
                    context.get('query', str(context))
                )
                
                if not (isinstance(auto_analysis, dict) and auto_analysis.get('error')):
                    comprehensive_analysis['analysis_components']['auto_intelligence'] = auto_analysis
                    comprehensive_analysis['capabilities_used'].append('auto_intelligence')
                    comprehensive_analysis['auto_enhanced'] = True
                    comprehensive_analysis['confidence_score'] += 0.1
            
            # 2. Instant Memory Search for Similar Contexts
            if self.lightning_memvid and include_memory:
                similar_contexts = safe_execute(
                    self.lightning_memvid.instant_search,
                    context.get('query', str(context)),
                    top_k=5
                )
                
                if not (isinstance(similar_contexts, dict) and similar_contexts.get('error')):
                    comprehensive_analysis['analysis_components']['memory_context'] = similar_contexts
                    comprehensive_analysis['capabilities_used'].append('lightning_memvid')
                    comprehensive_analysis['memory_enhanced'] = True
                    comprehensive_analysis['confidence_score'] += 0.2
            
            # 3. Recovery System Health Check
            if self.recovery_engine and include_recovery:
                health_check = safe_execute(self.recovery_engine.get_system_health)
                
                if not (isinstance(health_check, dict) and health_check.get('error')):
                    comprehensive_analysis['analysis_components']['system_health'] = health_check
                    comprehensive_analysis['capabilities_used'].append('recovery_engine')
                    
                    # Auto-recover if issues detected
                    if health_check.get('issues_detected'):
                        recovery_result = safe_execute(
                            self.recovery_engine.auto_recover,
                            health_check['issues_detected']
                        )
                        comprehensive_analysis['analysis_components']['recovery_actions'] = recovery_result
            
            # 4. Generate unified synthesis
            # This is where the "magic" happens - combining insights from all AI systems
            # into a single, coherent understanding that's smarter than any individual system
            synthesis = self._synthesize_intelligence(comprehensive_analysis['analysis_components'])
            comprehensive_analysis['unified_insights'] = synthesis.get('insights', [])
            comprehensive_analysis['recommendations'] = synthesis.get('recommendations', [])
            comprehensive_analysis['predictions'] = synthesis.get('predictions', [])
            
            # 5. Update confidence score based on capabilities used
            capabilities_count = len(comprehensive_analysis['capabilities_used'])
            if capabilities_count > 0:
                comprehensive_analysis['confidence_score'] = min(
                    0.95,
                    comprehensive_analysis['confidence_score'] + (capabilities_count * 0.1)
                )
            
            # 6. Store this interaction for future learning
            # Every interaction is saved so the system gets smarter over time
            # This creates a feedback loop where past experiences improve future responses
            if self.lightning_memvid:
                self._store_interaction(context, comprehensive_analysis)
            
        except Exception as e:
            comprehensive_analysis['error'] = str(e)
            comprehensive_analysis['confidence_score'] = 0.2
        
        # Calculate processing time
        comprehensive_analysis['processing_time'] = time.time() - start_time
        
        # Update performance metrics
        self._update_performance_metrics(comprehensive_analysis)
        
        return comprehensive_analysis
    
    def _synthesize_intelligence(self, components: Dict[str, Any]) -> Dict[str, Any]:
        """
        Synthesize insights from all intelligence components into unified understanding.
        This is where the magic happens - combining all sources into coherent insights.
        """
        synthesis = {
            'insights': [],
            'recommendations': [],
            'predictions': [],
            'confidence_factors': {}
        }
        
        # Extract insights from auto-intelligence
        if 'auto_intelligence' in components:
            auto_data = components['auto_intelligence']
            if isinstance(auto_data, dict):
                synthesis['insights'].extend(auto_data.get('insights', []))
                synthesis['recommendations'].extend(auto_data.get('recommendations', []))
        
        # Extract insights from memory context
        if 'memory_context' in components:
            memory_data = components['memory_context']
            if isinstance(memory_data, list) and memory_data:
                synthesis['insights'].append(f"Found {len(memory_data)} similar memories")
                # Add pattern-based insights
                patterns = self._extract_patterns_from_memories(memory_data)
                synthesis['insights'].extend(patterns)
        
        # Extract insights from system health
        if 'system_health' in components:
            health_data = components['system_health']
            if health_data.get('overall_health') != 'healthy':
                synthesis['recommendations'].append("System optimization recommended")
        
        # Generate predictions based on patterns
        if self.performance_history:
            predictions = self._generate_predictions()
            synthesis['predictions'].extend(predictions)
        
        # Remove duplicates while preserving order
        synthesis['insights'] = list(dict.fromkeys(synthesis['insights']))
        synthesis['recommendations'] = list(dict.fromkeys(synthesis['recommendations']))
        synthesis['predictions'] = list(dict.fromkeys(synthesis['predictions']))
        
        return synthesis
    
    def _extract_patterns_from_memories(self, memories: List[Any]) -> List[str]:
        """Extract meaningful patterns from similar memories"""
        patterns = []
        
        # Analyze memory types
        memory_types = {}
        for memory in memories:
            mem_type = memory.get('type', 'unknown') if isinstance(memory, dict) else 'text'
            memory_types[mem_type] = memory_types.get(mem_type, 0) + 1
        
        if memory_types:
            dominant_type = max(memory_types.items(), key=lambda x: x[1])
            patterns.append(f"Pattern: Primarily {dominant_type[0]} memories ({dominant_type[1]}/{len(memories)})")
        
        return patterns
    
    def _generate_predictions(self) -> List[str]:
        """Generate predictive insights based on performance history"""
        predictions = []
        
        if len(self.performance_history) > 5:
            # Analyze trends
            recent_times = [p['processing_time'] for p in self.performance_history[-5:]]
            avg_time = sum(recent_times) / len(recent_times)
            
            if avg_time > 1.0:
                predictions.append("Performance optimization needed - consider memory indexing")
            
            # Analyze capability usage
            recent_capabilities = []
            for p in self.performance_history[-10:]:
                recent_capabilities.extend(p.get('capabilities_used', []))
            
            if recent_capabilities:
                most_used = max(set(recent_capabilities), key=recent_capabilities.count)
                predictions.append(f"Primary capability trend: {most_used}")
        
        return predictions
    
    def _store_interaction(self, context: Dict[str, Any], analysis: Dict[str, Any]):
        """Store interaction for future learning and pattern recognition"""
        try:
            interaction_memory = {
                'type': 'unified_intelligence_interaction',
                'context': context,
                'analysis_summary': {
                    'insights_count': len(analysis.get('unified_insights', [])),
                    'recommendations_count': len(analysis.get('recommendations', [])),
                    'capabilities_used': analysis.get('capabilities_used', []),
                    'confidence_score': analysis.get('confidence_score', 0),
                    'processing_time': analysis.get('processing_time', 0)
                },
                'timestamp': datetime.now().isoformat()
            }
            
            # Store using lightning memvid for instant future access
            safe_execute(self.lightning_memvid.instant_save, interaction_memory)
            
        except Exception as e:
            # Silently fail - don't interrupt main process
            pass
    
    def _update_performance_metrics(self, analysis: Dict[str, Any]):
        """Track performance metrics for optimization"""
        metric = {
            'timestamp': datetime.now().isoformat(),
            'processing_time': analysis.get('processing_time', 0),
            'capabilities_used': analysis.get('capabilities_used', []),
            'confidence_score': analysis.get('confidence_score', 0)
        }
        
        self.performance_history.append(metric)
        
        # Keep only recent history (last 100 interactions)
        if len(self.performance_history) > 100:
            self.performance_history = self.performance_history[-100:]
    
    def _start_background_intelligence(self):
        """Start background processes for continuous intelligence enhancement"""
        # Background memory optimization
        if self.lightning_memvid:
            memory_optimizer = threading.Thread(
                target=self._background_memory_optimization,
                daemon=True
            )
            memory_optimizer.start()
            self.background_processes.append(memory_optimizer)
        
        # Background health monitoring
        if self.recovery_engine:
            health_monitor = threading.Thread(
                target=self._background_health_monitoring,
                daemon=True
            )
            health_monitor.start()
            self.background_processes.append(health_monitor)
    
    def _background_memory_optimization(self):
        """Continuously optimize memory storage and retrieval"""
        while True:
            try:
                time.sleep(300)  # Every 5 minutes
                
                # Optimize memory indices
                if hasattr(self.lightning_memvid, 'optimize_indices'):
                    safe_execute(self.lightning_memvid.optimize_indices)
                
                # Clean up old memories if needed
                if hasattr(self.lightning_memvid, 'cleanup_old_memories'):
                    safe_execute(self.lightning_memvid.cleanup_old_memories, days=30)
                    
            except Exception:
                # Continue running even if optimization fails
                pass
    
    def _background_health_monitoring(self):
        """Monitor system health and auto-recover when needed"""
        while True:
            try:
                time.sleep(600)  # Every 10 minutes
                
                # Check system health
                health_status = safe_execute(self.recovery_engine.get_system_health)
                
                if isinstance(health_status, dict) and health_status.get('issues_detected'):
                    # Auto-recover detected issues
                    safe_execute(self.recovery_engine.auto_recover, health_status['issues_detected'])
                    
            except Exception:
                # Continue monitoring even if check fails
                pass
    
    def get_session_summary(self) -> Dict[str, Any]:
        """Get comprehensive summary of the current session"""
        session_duration = datetime.now() - self.session_start
        
        summary = {
            'session_start': self.session_start.isoformat(),
            'session_duration': str(session_duration),
            'interactions_count': len(self.performance_history),
            'capabilities_status': {
                'auto_intelligence': bool(self.auto_intelligence),
                'lightning_memvid': bool(self.lightning_memvid),
                'recovery_engine': bool(self.recovery_engine)
            },
            'performance_summary': {},
            'session_insights': []
        }
        
        # Calculate performance summary
        if self.performance_history:
            processing_times = [p['processing_time'] for p in self.performance_history]
            summary['performance_summary'] = {
                'avg_processing_time': sum(processing_times) / len(processing_times),
                'min_processing_time': min(processing_times),
                'max_processing_time': max(processing_times),
                'total_interactions': len(self.performance_history)
            }
            
            # Most used capabilities
            all_capabilities = []
            for p in self.performance_history:
                all_capabilities.extend(p.get('capabilities_used', []))
            
            if all_capabilities:
                capability_counts = {}
                for cap in all_capabilities:
                    capability_counts[cap] = capability_counts.get(cap, 0) + 1
                summary['most_used_capabilities'] = capability_counts
        
        # Add session insights
        if self.intelligence_context:
            summary['session_insights'] = self.intelligence_context.session_insights
        
        return summary
    
    @contextmanager
    def enhanced_context(self):
        """Context manager for enhanced intelligence operations"""
        # Store original context
        original_context = self.intelligence_context
        
        try:
            # Enhance context for this operation
            self.intelligence_context = self._generate_intelligence_context()
            yield self
        finally:
            # Restore original context
            self.intelligence_context = original_context
    
    def shutdown(self):
        """Gracefully shutdown all intelligence systems"""
        # Stop background processes
        for process in self.background_processes:
            if process.is_alive():
                process.join(timeout=1.0)
        
        # Save final session data
        if self.lightning_memvid:
            session_summary = self.get_session_summary()
            safe_execute(
                self.lightning_memvid.instant_save,
                {
                    'type': 'session_summary',
                    'summary': session_summary,
                    'timestamp': datetime.now().isoformat()
                }
            )


# Global instance for easy access
_unified_intelligence = None

def get_unified_intelligence() -> UnifiedIntelligenceOrchestrator:
    """Get or create the global unified intelligence instance"""
    global _unified_intelligence
    if _unified_intelligence is None:
        _unified_intelligence = UnifiedIntelligenceOrchestrator()
    return _unified_intelligence


# 🚀 AUTO-ACTIVATION: Seamless Intelligence Enhancement
# This automatically starts the unified intelligence system when the module is imported
# This means users get AI enhancement without any setup - it "just works"
if AUTO_INTELLIGENCE_AVAILABLE:
    try:
        # Create the global orchestrator automatically
        # This makes AI enhancement available immediately
        _unified_intelligence = UnifiedIntelligenceOrchestrator()
    except:
        # Silently fail if auto-activation doesn't work
        # Users can still manually create an orchestrator if needed
        pass