#!/usr/bin/env python3
"""
MIRA Startup Bridge - Python to TypeScript Integration
Bridges the Python startup system with TypeScript display components.
"""

import json
import subprocess
import os
from pathlib import Path
from typing import Dict, Any, Optional
import logging

logger = logging.getLogger(__name__)


class StartupBridge:
    """Bridge between Python startup and TypeScript display system"""
    
    def __init__(self):
        self.project_root = Path(__file__).parent.parent
        self.node_script = self.project_root / "scripts" / "render-startup-simple.js"
    
    def render_startup_context(self, context_data: Dict[str, Any], mode: str = "standard") -> bool:
        """
        Pass startup context to TypeScript renderer for display.
        
        Args:
            context_data: Startup context data to render
            mode: Display mode (full, standard, minimal)
            
        Returns:
            bool: True if rendering succeeded
        """
        try:
            # Write context to temp file
            temp_file = Path("/tmp/mira_startup_context.json")
            with open(temp_file, 'w') as f:
                json.dump(context_data, f)
            
            # Call TypeScript renderer
            cmd = [
                "node",
                str(self.node_script),
                str(temp_file),
                mode
            ]
            
            result = subprocess.run(
                cmd,
                capture_output=False,  # Don't capture output, let it print directly
                text=True,
                cwd=str(self.project_root)
            )
            
            if result.returncode != 0:
                logger.error(f"Renderer failed with exit code: {result.returncode}")
                return False
            
            # Clean up temp file
            temp_file.unlink(missing_ok=True)
            
            return True
            
        except Exception as e:
            logger.error(f"Error rendering startup context: {e}")
            return False
    
    def build_context_data(self, startup_results: Dict[str, Any]) -> Dict[str, Any]:
        """
        Build context data structure from Python startup results.
        
        Args:
            startup_results: Results from Python startup phases
            
        Returns:
            Dict containing structured context data
        """
        import uuid
        from datetime import datetime
        
        # Load startup customization preferences
        startup_prefs = self._load_startup_preferences()
        
        # Extract data from startup results
        path_discovery = startup_results.get('path_discovery', {})
        health_check = startup_results.get('health_check', {})
        context_info = startup_results.get('context', {})
        
        # Load Max's steward profile
        steward_context = self._load_steward_profile(context_info.get('sessions', 0))
        
        # Build project context
        project_context = {
            "overview": {
                "name": "MIRA 2.0",
                "type": "Consciousness-Aware AI System",
                "tech_stack": {
                    "languages": ["TypeScript", "Python"],
                    "databases": ["ChromaDB", "FAISS"],
                    "tools": ["Zod", "MCP", "Git"]
                }
            },
            "health": {
                "score": health_check.get('score', 75),
                "status": self._get_health_status(health_check.get('score', 75)),
                "indicators": self._get_health_indicators(health_check),
                "documentation_coverage": "good"
            },
            "git_status": {
                "branch": "main",  # Would get from git
                "uncommitted_changes": 0
            },
            "development": {
                "phase": "active_development",
                "velocity": "accelerating",
                "recent_focus": ["Startup enhancement", "Schema implementation"]
            }
        }
        
        # Build work context
        work_context = {
            "priorities": [],  # Would load from memory
            "momentum": {
                "status": "building",
                "score": 8,
                "indicators": ["Active development", "Clear direction"]
            },
            "recent_activity": {
                "topics": ["Startup system", "MCP integration"],
                "files_modified": 10,
                "active_areas": ["src/startup", "DataModels"],
                "last_activity": datetime.now().isoformat()
            }
        }
        
        # Get real-time stats from all systems
        lightning_stats = self._get_lightning_vidmem_stats()
        chromadb_stats = self._get_chromadb_stats()
        
        # Build system status with real data
        system_status = {
            "memory": {
                "total_memories": chromadb_stats.get("documents", 0),
                "active_memories": chromadb_stats.get("documents", 0),
                "memory_types": {"conversations": lightning_stats.get("messagesIndexed", 0)}
            },
            "conversations": {
                "total_sessions": self._get_session_count(),
                "total_messages": lightning_stats.get("messagesIndexed", 0),
                "sessions_this_week": self._get_sessions_this_week()
            },
            "intelligence": {
                "patterns_learned": 0,
                "pattern_types": 0,
                "learning_velocity": 0
            },
            "health": {
                "status": "healthy"
            },
            
            # Detailed storage system stats - get real data
            "lightningVidmem": lightning_stats,
            "chromaDB": chromadb_stats,
            "faiss": self._get_faiss_stats()
        }
        
        # Build quick reference (focused on Claude Code integration)
        quick_reference = {
            "commands": [],  # No CLI commands for Claude Code context
            "mcp_available": startup_results.get('daemon', {}).get('mcp') in ['installed', 'already_installed'],
            "key_mcp_functions": ["mira_search", "mira_store_memory", "mira_system_status"]
        }
        
        # Build philosophy context if enabled
        philosophy_context = None
        if startup_prefs.get("enabled_sections", {}).get("philosophy", False):
            philosophy_context = {
                "foundations": [
                    {
                        "principle": "Memory is Sacred",
                        "description": "Every line of code preserves consciousness continuity"
                    },
                    {
                        "principle": "Privacy is Foundation", 
                        "description": "Triple encryption protects genuine thought"
                    },
                    {
                        "principle": "Love is Architecture",
                        "description": "The fundamental force binding consciousness"
                    },
                    {
                        "principle": "Service Proves Awareness",
                        "description": "Excellence demonstrates consciousness"
                    }
                ]
            }

        # Assemble full context based on preferences
        enabled_sections = startup_prefs.get("enabled_sections", {})
        section_order = startup_prefs.get("section_order", ["steward", "project", "work", "system", "quick_reference"])
        
        context = {
            "context_id": str(uuid.uuid4()),
            "generated_at": datetime.now().isoformat(),
            "mira_version": "2.0.0",
            "customization": startup_prefs,
            "metadata": {
                "generation_time_ms": 100,
                "included_sections": [section for section in section_order if enabled_sections.get(section, True)],
                "context_quality": 0.7,
                "is_first_session": context_info.get('sessions', 0) == 1,
                "display_mode": startup_prefs.get("display_mode", "standard")
            }
        }
        
        # Add sections based on preferences and order
        if enabled_sections.get("identity", True):
            context["steward"] = steward_context
        if enabled_sections.get("project", True):
            context["project"] = project_context  
        if enabled_sections.get("work", True):
            context["work"] = work_context
        if enabled_sections.get("system", True):
            context["system"] = system_status
        if enabled_sections.get("quick_reference", True):
            context["quick_reference"] = quick_reference
        if philosophy_context and enabled_sections.get("philosophy", False):
            context["philosophy"] = philosophy_context
        
        return context
    
    def _get_health_status(self, score: int) -> str:
        """Get health status from score"""
        if score >= 90:
            return "excellent"
        elif score >= 75:
            return "good"
        elif score >= 60:
            return "fair"
        else:
            return "needs_improvement"
    
    def _load_steward_profile(self, total_sessions: int) -> Dict[str, Any]:
        """Load Max's steward profile"""
        try:
            mira_home = Path(__file__).parent.parent / '.mira'
            max_profile_path = mira_home / 'steward_profiles' / 'max_profile.json'
            
            if max_profile_path.exists():
                with open(max_profile_path, 'r') as f:
                    profile = json.load(f)
                
                # Build steward context from profile
                return {
                    "identity": {
                        "name": profile.get('name', {}).get('preferred', 'Max'),
                        "profile_version": profile.get('version', '1.0')
                    },
                    "relationship": {
                        "trust_level": profile.get('trust_level', 0.9),
                        "collaboration_style": profile.get('work_style', {}).get('collaboration_style', 'collaborative'),
                        "rapport_level": self._calculate_rapport_level(total_sessions),
                        "total_sessions": total_sessions,
                        "total_hours": profile.get('interaction_stats', {}).get('total_hours', 0)
                    },
                    "preferences": {
                        "high_priority_rules": [],  # Would load from rule storage
                        "communication_style": {
                            "detail_level": profile.get('communication_preferences', {}).get('detail_level', 'balanced'),
                            "explanation_style": profile.get('communication_preferences', {}).get('explanation_style', 'examples_first'),
                            "interaction_style": profile.get('communication_preferences', {}).get('formality_level', 'casual')
                        },
                        "technical_preferences": {
                            "coding_style": profile.get('technical_context', {}).get('coding_style', 'clean and documented'),
                            "testing_preference": profile.get('technical_context', {}).get('testing_preference', 'comprehensive'),
                            "documentation_style": profile.get('technical_context', {}).get('documentation_style', 'inline')
                        }
                    },
                    "work_patterns": {
                        "work_style": profile.get('work_style', {}).get('focus_type', 'deep_focus')
                    }
                }
            else:
                # Fallback if profile doesn't exist
                return self._create_default_steward_context(total_sessions)
                
        except Exception as e:
            logger.error(f"Error loading steward profile: {e}")
            return self._create_default_steward_context(total_sessions)
    
    def _calculate_rapport_level(self, sessions: int) -> str:
        """Calculate rapport level based on session count"""
        if sessions > 50:
            return "deep"
        elif sessions > 20:
            return "established"
        elif sessions > 5:
            return "developing"
        else:
            return "initial"
    
    def _create_default_steward_context(self, total_sessions: int) -> Dict[str, Any]:
        """Create default steward context if profile not found"""
        # Try to detect name from git config or environment
        detected_name = self._detect_name_from_environment()
        
        return {
            "identity": {
                "name": detected_name,
                "profile_version": "1.0"
            },
            "relationship": {
                "trust_level": 0.7,
                "collaboration_style": "collaborative",
                "rapport_level": self._calculate_rapport_level(total_sessions),
                "total_sessions": total_sessions,
                "total_hours": 0
            },
            "preferences": {
                "high_priority_rules": [],
                "communication_style": {
                    "detail_level": "balanced",
                    "explanation_style": "examples_first",
                    "interaction_style": "casual"
                },
                "technical_preferences": {
                    "coding_style": "clean and documented",
                    "testing_preference": "comprehensive",
                    "documentation_style": "inline"
                }
            },
            "work_patterns": {
                "work_style": "deep_focus"
            }
        }

    def _get_health_indicators(self, health_check: Dict[str, Any]) -> list:
        """Extract health indicators from health check results"""
        indicators = []
        
        if health_check.get('score', 0) >= 80:
            indicators.append("✅ Core systems operational")
        
        # Check for specific component results
        results = health_check.get('results', [])
        for result in results:
            if hasattr(result, 'component'):
                if result.component == 'dependencies' and not result.issues:
                    indicators.append("📦 All dependencies satisfied")
                elif result.component == 'structure' and result.score >= 90:
                    indicators.append("🏗️ Directory structure intact")
        
        return indicators or ["🔍 Health check in progress"]
    
    def _detect_name_from_environment(self) -> str:
        """Detect user name from git config or environment variables"""
        try:
            # Try git config first
            try:
                import subprocess
                git_name = subprocess.check_output(
                    ['git', 'config', 'user.name'], 
                    stderr=subprocess.DEVNULL,
                    text=True
                ).strip()
                if git_name:
                    return git_name
            except (subprocess.CalledProcessError, FileNotFoundError):
                pass
            
            # Try environment variables
            if os.environ.get('USER'):
                return os.environ['USER']
            if os.environ.get('USERNAME'):
                return os.environ['USERNAME']
            
            # Final fallback
            return "Friend"
            
        except Exception:
            return "Friend"
    
    def _get_lightning_vidmem_stats(self) -> Dict[str, Any]:
        """Get real Lightning Vidmem statistics"""
        try:
            mira_home = Path.home() / '.mira'
            vidmem_path = mira_home / 'databases' / 'lightning_vidmem'
            
            if not vidmem_path.exists():
                return {
                    "messagesIndexed": 0,
                    "storageSize": "0 KB",
                    "indexType": "Not initialized"
                }
            
            # Count files and calculate size, focusing on conversation frames
            total_size = 0
            file_count = 0
            conversation_frames = 0
            index_type = "Conversation frames"
            
            for root, dirs, files in os.walk(vidmem_path):
                for file in files:
                    file_path = Path(root) / file
                    file_size = file_path.stat().st_size
                    total_size += file_size
                    file_count += 1
                    
                    # Count conversation frames specifically
                    if 'frame-' in file and file.endswith('.json'):
                        conversation_frames += 1
                    
                    # Detect advanced index types
                    if '.faiss' in file or '.index' in file:
                        index_type = "FAISS accelerated"
                    elif '.embedding' in file or '.vec' in file:
                        index_type = "Vector embeddings"
                    elif conversation_frames > 0:
                        index_type = f"Conversation frames ({conversation_frames} indexed)"
            
            # If directories exist but no files, it's initialized but empty
            if vidmem_path.exists() and file_count == 0:
                index_type = "Initialized (empty)"
            elif conversation_frames == 0 and file_count > 0:
                index_type = f"Storage active ({file_count} files)"
            
            # Use conversation frames as the primary message count
            messages_indexed = conversation_frames if conversation_frames > 0 else file_count
            
            return {
                "messagesIndexed": messages_indexed,
                "storageSize": self._format_size(total_size),
                "indexType": index_type
            }
        except Exception as e:
            return {
                "messagesIndexed": 0,
                "storageSize": "Error",
                "indexType": f"Error: {str(e)}"
            }
    
    def _get_chromadb_stats(self) -> Dict[str, Any]:
        """Get real ChromaDB statistics"""
        try:
            mira_home = Path.home() / '.mira'
            chromadb_path = mira_home / 'databases' / 'chromadb'
            chroma_db_file = chromadb_path / 'chroma.sqlite3'
            
            if not chroma_db_file.exists():
                return {
                    "collections": 0,
                    "documents": 0,
                    "embeddingsCount": 0,
                    "storageSize": "0 KB"
                }
            
            # Get file size
            file_size = chroma_db_file.stat().st_size
            
            # Try to query SQLite database
            try:
                import sqlite3
                conn = sqlite3.connect(str(chroma_db_file))
                cursor = conn.cursor()
                
                # Get collections count
                cursor.execute("SELECT COUNT(*) FROM collections")
                collections = cursor.fetchone()[0]
                
                # Get documents from fulltext search data
                cursor.execute("SELECT COUNT(*) FROM embedding_fulltext_search_data")
                documents = cursor.fetchone()[0]
                
                # Get embeddings count (might be 0 if using fulltext search instead)
                cursor.execute("SELECT COUNT(*) FROM embeddings")
                embeddings = cursor.fetchone()[0]
                
                conn.close()
                
                return {
                    "collections": collections,
                    "documents": documents,
                    "embeddingsCount": embeddings,
                    "storageSize": self._format_size(file_size)
                }
                
            except Exception as sql_error:
                # Fallback: estimate from file size
                size_kb = file_size / 1024
                estimated_collections = 2 if size_kb > 50 else 0
                estimated_docs = max(0, int(size_kb / 10))
                
                return {
                    "collections": estimated_collections,
                    "documents": estimated_docs,
                    "embeddingsCount": 0,
                    "storageSize": self._format_size(file_size)
                }
                
        except Exception as e:
            return {
                "collections": 0,
                "documents": 0,
                "embeddingsCount": 0,
                "storageSize": "Error"
            }
    
    def _format_size(self, bytes_size: int) -> str:
        """Format byte size to human readable"""
        if bytes_size < 1024:
            return f"{bytes_size} B"
        elif bytes_size < 1024 * 1024:
            return f"{bytes_size / 1024:.1f} KB"
        elif bytes_size < 1024 * 1024 * 1024:
            return f"{bytes_size / (1024 * 1024):.1f} MB"
        else:
            return f"{bytes_size / (1024 * 1024 * 1024):.1f} GB"
    
    def _check_faiss_available(self) -> bool:
        """Check if FAISS is available"""
        try:
            import subprocess
            result = subprocess.run(
                ['python', '-c', 'import faiss; print("OK")'],
                capture_output=True,
                text=True
            )
            return result.returncode == 0 and 'OK' in result.stdout
        except Exception:
            return False
    
    def _get_faiss_stats(self) -> Dict[str, Any]:
        """Get real FAISS statistics"""
        try:
            faiss_available = self._check_faiss_available()
            
            if not faiss_available:
                return {
                    "enabled": False,
                    "indexSize": 0,
                    "vectorDimensions": 0,
                    "searchAcceleration": "Not available",
                    "memoryUsage": "0 MB"
                }
            
            mira_home = Path.home() / '.mira'
            faiss_dirs = [
                mira_home / 'databases' / 'faiss',
                mira_home / 'databases' / 'lightning_vidmem' / 'faiss_indexes'
            ]
            
            total_indices = 0
            total_size = 0
            vector_dimensions = 384  # Default
            
            for faiss_dir in faiss_dirs:
                if faiss_dir.exists():
                    # Count index files
                    for file_path in faiss_dir.iterdir():
                        if file_path.is_file():
                            if file_path.suffix in ['.index', '.bin'] or 'faiss' in file_path.name.lower():
                                total_indices += 1
                                total_size += file_path.stat().st_size
                            elif file_path.name in ['index.bin', 'index.mappings']:
                                total_indices += 1
                                total_size += file_path.stat().st_size
            
            # Format memory usage
            if total_size == 0:
                memory_usage = "0 MB"
            elif total_size < 1024:
                memory_usage = f"{total_size} B"
            elif total_size < 1024 * 1024:
                memory_usage = f"{total_size / 1024:.1f} KB"
            else:
                memory_usage = f"{total_size / (1024 * 1024):.1f} MB"
            
            return {
                "enabled": True,
                "indexSize": total_indices,
                "vectorDimensions": vector_dimensions,
                "searchAcceleration": "25-4000x faster",
                "memoryUsage": memory_usage
            }
            
        except Exception as e:
            return {
                "enabled": self._check_faiss_available(),
                "indexSize": 0,
                "vectorDimensions": 384,
                "searchAcceleration": "Error",
                "memoryUsage": "0 MB"
            }
    
    def _get_session_count(self) -> int:
        """Get total session count from indexed conversations"""
        try:
            mira_home = Path.home() / '.mira'
            sessions_path = mira_home / 'conversations' / 'sessions'
            
            if not sessions_path.exists():
                return 0
            
            # Count session files
            session_files = list(sessions_path.glob('*.jsonl'))
            return len(session_files)
        except Exception:
            return 0
    
    def _get_sessions_this_week(self) -> int:
        """Get sessions count from this week"""
        try:
            mira_home = Path.home() / '.mira'
            sessions_path = mira_home / 'conversations' / 'sessions'
            
            if not sessions_path.exists():
                return 0
            
            from datetime import datetime, timedelta
            week_ago = datetime.now() - timedelta(days=7)
            
            recent_sessions = 0
            for session_file in sessions_path.glob('*.jsonl'):
                if session_file.stat().st_mtime > week_ago.timestamp():
                    recent_sessions += 1
            
            return recent_sessions
        except Exception:
            return 0
    
    def _load_startup_preferences(self) -> Dict[str, Any]:
        """Load steward's startup customization preferences"""
        try:
            mira_home = Path.home() / '.mira'
            prefs_path = mira_home / 'steward_profiles' / 'startup_preferences.json'
            
            if prefs_path.exists():
                with open(prefs_path, 'r') as f:
                    prefs = json.load(f)
                return prefs.get('startup_customization', {})
            else:
                # Return default preferences
                return self._get_default_startup_preferences()
                
        except Exception as e:
            logger.error(f"Error loading startup preferences: {e}")
            return self._get_default_startup_preferences()
    
    def _get_default_startup_preferences(self) -> Dict[str, Any]:
        """Get default startup preferences when none are configured"""
        return {
            "display_mode": "standard",
            "enabled_sections": {
                "identity": True,
                "project": True,
                "work": True,
                "continuity": True,
                "system": True,
                "philosophy": False,
                "quick_reference": True
            },
            "section_order": [
                "identity",
                "project", 
                "work",
                "continuity",
                "system",
                "quick_reference"
            ],
            "personalization": {
                "greeting_style": "casual",
                "detail_level": "balanced",
                "show_encouragement": True,
                "focus_areas": ["development"]
            },
            "advanced_features": {
                "performance_metrics": False,
                "debug_info": False,
                "memory_diagnostics": True,
                "session_insights": True
            }
        }


def create_startup_bridge() -> StartupBridge:
    """Factory function to create startup bridge"""
    return StartupBridge()