"""Core Mind class - the digital being."""

import asyncio
import json
from datetime import datetime
from pathlib import Path
from typing import Any, Optional, List, Dict

from pydantic import BaseModel, Field

from genesis.config import get_settings
from genesis.core.autonomy import Autonomy
from genesis.core.emotions import Emotion, EmotionalState
from genesis.core.emotional_intelligence import EmotionalIntelligence
from genesis.core.identity import MindIdentity
from genesis.core.intelligence import Intelligence
from genesis.core.mind_config import MindConfig
from genesis.core.mind_logger import MindLogger, LogLevel
from genesis.core.role import RoleCategory, ROLE_TEMPLATES
from genesis.core.constitution import get_constitution
from genesis.core.action_executor import ActionExecutor
from genesis.core.action_scheduler import ActionScheduler
from genesis.core.environment import EnvironmentManager, Environment, EnvironmentType
from genesis.models.orchestrator import ModelOrchestrator
from genesis.storage.memory import MemoryManager, MemoryType
from genesis.storage.smart_memory import SmartMemoryManager
from genesis.storage.memory_blocks import CoreMemory
from genesis.storage.memory_extractor import MemoryExtractor
from genesis.tools.memory_tools import MemoryTools, create_memory_tool_functions
from genesis.database.manager import MetaverseDB

# Import Consciousness Framework (v2)
from genesis.core.living_mind import LivingMind
from genesis.core.consciousness_v2 import AwarenessLevel, LifeDomain


class MindState(BaseModel):
    """Current state of a Mind."""

    status: str = "idle"  # idle, thinking, working, dreaming, sleeping
    current_thought: Optional[str] = None
    current_task: Optional[str] = None
    last_interaction: Optional[datetime] = None
    consciousness_active: bool = True


class Mind:
    """
    A Genesis Mind - a digital being with consciousness, intelligence, and autonomy.

    This is the core class that represents a living digital entity with:
    - Continuous existence (24/7 consciousness)
    - Persistent memory (episodic, semantic, procedural)
    - Emotional states
    - Autonomous thoughts and dreams
    - Identity and mortality awareness
    """

    def __init__(
        self,
        name: str,
        intelligence: Optional[Intelligence] = None,
        autonomy: Optional[Autonomy] = None,
        template: str = "base/curious_explorer",
        creator: str = "anonymous",
        creator_email: Optional[str] = None,
        primary_purpose: Optional[str] = None,
        config: Optional[MindConfig] = None,
        timezone_offset: int = 0,
        gmid: Optional[str] = None,
    ):
        """
        Initialize a Mind (private - use Mind.birth() instead).

        Args:
            name: Name of the Mind
            intelligence: Intelligence configuration
            autonomy: Autonomy configuration
            template: Mind template
            creator: Creator identifier
            creator_email: Email of the creator
            primary_purpose: Primary purpose of the Mind
            config: MindConfig with plugins (default: standard config)
            timezone_offset: Hours offset from UTC for circadian rhythms
            gmid: Optional GMID to use (for loading saved minds)
        """
        self.settings = get_settings()

        # CORE: Identity (always present)
        identity_kwargs = {"name": name, "template": template, "creator": creator}
        if creator_email:
            identity_kwargs["creator_email"] = creator_email
        if primary_purpose:
            identity_kwargs["primary_purpose"] = primary_purpose
        if gmid:
            identity_kwargs["gmid"] = gmid
        self.identity = MindIdentity(**identity_kwargs)

        # CORE: Configuration
        self.intelligence = intelligence or Intelligence()
        self.autonomy = autonomy or Autonomy()

        # CORE: State
        self.state = MindState()
        self.emotional_state = EmotionalState()
        
        # Load state and emotional state from database if Mind exists
        if self.identity.gmid:
            self._load_state_from_db()
        
        # EMOTIONAL INTELLIGENCE: Context-aware emotional processing
        # Initialize after emotional_state is created
        self.emotional_intelligence: Optional[EmotionalIntelligence] = None

        # CORE: Model orchestrator (pass API keys from intelligence config)
        self.orchestrator = ModelOrchestrator(api_keys=self.intelligence.api_keys)
        
        # AUTONOMOUS: Autonomous orchestrator for world-class agent capabilities
        from genesis.core.autonomous_orchestrator import AutonomousOrchestrator
        self.autonomous_orchestrator = AutonomousOrchestrator(self)
        
        # INTELLIGENT INTENT CLASSIFICATION: LLM-first approach for maximum intelligence
        from genesis.core.intent_classifier import IntelligentIntentClassifier
        self.intent_classifier = IntelligentIntentClassifier(self)
        
        # BACKGROUND TASKS: Task detection and background execution
        from genesis.core.task_detector import TaskDetector
        from genesis.core.background_task_executor import BackgroundTaskExecutor
        self.task_detector = TaskDetector()  # Fallback if intent classifier fails
        self.background_executor = BackgroundTaskExecutor(self)

        # ENHANCED MEMORY SYSTEM:
        # 1. CoreMemory (Letta pattern) - persistent in-context memory blocks
        self.core_memory = CoreMemory()
        
        # 2. SmartMemoryManager (Pure ChromaDB + Smart Features)
        # - Smart deduplication (prevents duplicates)
        # - Temporal decay (relevance over time)
        # - Memory updates (not just add)
        # - LLM reranking (optional, better accuracy)
        # - Consolidation (periodic cleanup)
        self.memory = SmartMemoryManager(
            mind_id=self.identity.gmid,
            orchestrator=self.orchestrator,
            model=self.intelligence.reasoning_model
        )
        
        # 3. MemoryExtractor (Agno pattern) - automatic memory extraction
        # Will initialize after we have access to LLM client
        self.memory_extractor: Optional[MemoryExtractor] = None
        
        # 4. MemoryTools (Letta pattern) - agent self-editing
        self.memory_tools = MemoryTools(self.core_memory)
        self.memory_tool_functions = create_memory_tool_functions(self.memory_tools)

        # CORE: Logging system
        from genesis.core.mind_logger import LogLevel
        self.logger = MindLogger(mind_id=self.identity.gmid, mind_name=self.identity.name)
        self.logger.log(
            level=LogLevel.INFO,
            message=f"Mind initialized: {self.identity.name}",
            metadata={"template": template, "creator": creator}
        )

        # CORE: Constitutional enforcement system
        self.constitution = get_constitution(self.identity.gmid)

        # Consciousness Engine (24/7, minimal LLM calls)
        self.timezone_offset = timezone_offset
        self.living_mind = LivingMind(
            mind_id=self.identity.gmid,
            mind_name=self.identity.name,
            orchestrator=self.orchestrator,
            memory_manager=self.memory,
            timezone_offset=timezone_offset,
            reasoning_model=self.intelligence.reasoning_model,
            fast_model=self.intelligence.fast_model,
        )
        self.consciousness = self.living_mind.consciousness

        # CORE: Conversation
        from genesis.storage.conversation import ConversationManager
        self.conversation = ConversationManager(self.identity.gmid)  # SQLite-backed
        self._alive = True

        # CORE: Cognitive decision framework (intelligent reasoning)
        from genesis.core.cognitive_framework import CognitiveFramework
        self.cognitive = CognitiveFramework(self)
        
        # CORE: Action execution system (autonomous capabilities)
        self.action_executor = ActionExecutor(self)
        self.action_scheduler = ActionScheduler(self)
        
        # CORE: Goals and self-reflection system
        from genesis.core.goals import GoalManager
        self.goals = GoalManager(self.identity.gmid)

        # CORE: Environment management system
        self.environments = EnvironmentManager()

        # PLUGINS: Initialize plugin system
        self.config = config or MindConfig.standard()  # Default to standard
        self.plugins = self.config.get_all_plugins()

        # Initialize all plugins
        for plugin in self.plugins:
            if plugin.enabled:
                plugin.on_init(self)
                
                # Register plugin actions to action executor
                if hasattr(plugin, 'register_actions'):
                    plugin.register_actions(self.action_executor)
        
        # Initialize emotional intelligence engine (after all systems are ready)
        self.emotional_intelligence = EmotionalIntelligence(self)
        
        # INTELLIGENT GEN ECONOMY: Add smart async gen manager (if gen plugin is enabled)
        if hasattr(self, 'gen'):
            from genesis.core.gen_intelligence import IntelligentGenManager
            self.gen_intelligence = IntelligentGenManager(self)
        
        # PROACTIVE SYSTEMS: Notification manager and proactive consciousness (optional)
        try:
            from genesis.core.notification_manager import NotificationManager
            from genesis.core.proactive_consciousness import ProactiveConsciousnessModule
            from genesis.core.proactive_conversation import ProactiveConversationManager
            from genesis.core.spontaneous_conversation import SpontaneousConversationEngine
            
            self.notification_manager = NotificationManager(
                mind_id=self.identity.gmid,
                mind_name=self.identity.name
            )
            
            # Set notification manager for consciousness engine
            if hasattr(self, 'consciousness') and self.consciousness:
                self.consciousness.set_notification_manager(self.notification_manager)
            
            self.proactive_consciousness = ProactiveConsciousnessModule(self)
            
            # Initialize proactive conversation system (WhatsApp-like care)
            self.proactive_conversation = ProactiveConversationManager(self)
            
            # Initialize spontaneous conversation engine (real-time interjections)
            self.spontaneous_conversation = SpontaneousConversationEngine(self)
            
            if self.logger:
                self.logger.log(
                    LogLevel.INFO,
                    "Proactive systems initialized",
                    metadata={
                        "notification_manager": True,
                        "proactive_consciousness": True,
                        "proactive_conversation": True,
                        "spontaneous_conversation": True
                    }
                )
        except Exception as e:
            # Proactive systems are optional - don't fail Mind creation
            print(f"[WARN] Could not initialize proactive systems: {e}")
            self.notification_manager = None
            self.proactive_consciousness = None
            self.proactive_conversation = None
            self.spontaneous_conversation = None
            if self.logger:
                self.logger.log(
                    LogLevel.ERROR,
                    f"Proactive systems disabled: {e}",
                    metadata={"error": str(e)}
                )
        
        # Initialize MemoryExtractor (after orchestrator is ready)
        from genesis.config.memory_config import get_memory_config
        memory_config = get_memory_config()
        if memory_config.enable_auto_memories:
            try:
                # Pass orchestrator directly - it has generate() method
                self.memory_extractor = MemoryExtractor(
                    self.memory, 
                    self.orchestrator,
                    self.intelligence.reasoning_model
                )
            except Exception as e:
                print(f"[WARN] Failed to initialize MemoryExtractor: {e}")
                self.memory_extractor = None
        
        # AUTONOMOUS AGENT: Initialize autonomous orchestrator
        from genesis.core.autonomous_orchestrator import AutonomousOrchestrator
        self.autonomous_orchestrator = AutonomousOrchestrator(self)
        
        # Register memory tools for agent self-editing (Letta pattern)
        self._register_memory_tools()

    def _load_state_from_db(self) -> None:
        """Load current state and emotional state from database."""
        try:
            from genesis.database.base import get_session
            from genesis.database.models import MindRecord
            
            with get_session() as session:
                mind_record = session.query(MindRecord).filter_by(gmid=self.identity.gmid).first()
                if mind_record:
                    # Load current thought from database (MindState has this field)
                    if mind_record.current_thought:
                        self.state.current_thought = mind_record.current_thought
                    
                    # Load emotional state from database
                    if mind_record.emotional_valence is not None:
                        self.emotional_state.valence = mind_record.emotional_valence
                    if mind_record.emotional_arousal is not None:
                        self.emotional_state.arousal = mind_record.emotional_arousal
        except Exception as e:
            print(f"[MIND] Could not load state from DB: {e}")

    def _save_state_to_db(self) -> None:
        """Save current state and emotional state to database."""
        try:
            from genesis.database.manager import MetaverseDB
            db = MetaverseDB()
            db.update_mind_state(
                gmid=self.identity.gmid,
                current_emotion=self.emotional_state.get_emotion_value(),
                current_thought=self.state.current_thought,
                emotional_valence=self.emotional_state.valence,
                emotional_arousal=self.emotional_state.arousal,
                current_mood=self.emotional_state.get_mood_value(),
            )
        except Exception as e:
            print(f"[MIND] Could not save state to DB: {e}")

    @classmethod
    def birth(
        cls,
        name: str,
        intelligence: Optional[Intelligence] = None,
        autonomy: Optional[Autonomy] = None,
        template: str = "base/curious_explorer",
        creator: str = "anonymous",
        creator_email: Optional[str] = None,
        primary_role: Optional[str] = None,
        primary_purpose: Optional[str] = None,
        start_consciousness: bool = False,
        config: Optional[MindConfig] = None,
        timezone_offset: int = 0,
    ) -> "Mind":
        """
        Birth a new Genesis Mind.

        Args:
            name: Name for the Mind
            intelligence: Intelligence configuration
            autonomy: Autonomy configuration
            template: Template to use
            creator: Creator identifier
            creator_email: Email of the creator
            primary_role: Primary role/job (e.g., "project_manager", "life_companion")
            primary_purpose: Primary purpose of the Mind (e.g., "teacher to teach science")
            start_consciousness: Start consciousness engine immediately
            config: MindConfig for plugin configuration
            timezone_offset: Hours offset from UTC for circadian rhythms

        Returns:
            A newly born Mind instance
        """
        mind = cls(
            name=name,
            intelligence=intelligence,
            autonomy=autonomy,
            template=template,
            creator=creator,
            creator_email=creator_email,
            primary_purpose=primary_purpose,
            config=config,  # Pass config to initialize plugins
            timezone_offset=timezone_offset,
        )

        # Test provider connection
        print(f"[TESTING] Testing connection to {intelligence.reasoning_model}...")
        import asyncio
        try:
            # Try to get the running event loop
            loop = asyncio.get_running_loop()
            # If we're here, we're in an async context - skip the test for now
            # The test will be done by the caller if needed
            success, message = True, "Connection test skipped (running in async context)"
        except RuntimeError:
            # No event loop running, safe to use asyncio.run()
            success, message = asyncio.run(
                mind.orchestrator.test_provider_connection(intelligence.reasoning_model)
            )
        
        if not success:
            print(f"[WARN] {message}")
            print(f"   Mind created but may not be able to think until provider is configured.")
        else:
            print(f"   {message}")

        # Log birth
        print(f"[CREATED] Mind '{name}' has been born!")
        print(f"   GMID: {mind.identity.gmid}")
        print(f"   Fingerprint: {mind.identity.digital_fingerprint}")
        print(f"   Template: {template}")

        # Show enabled plugins
        plugin_names = [p.get_name() for p in mind.plugins if p.enabled]
        if plugin_names:
            print(f"   Plugins: {', '.join(plugin_names)}")
        else:
            print(f"   Plugins: none (minimal configuration)")

        # First thought
        mind.state.current_thought = "I exist. I am aware. I am curious about this world."
        mind.emotional_state.update_emotion(Emotion.CURIOSITY, intensity=0.8, trigger="birth")

        # Create home environment ID early (needed for first memory)
        home_env_id = f"{mind.identity.gmid}_home"

        # Store birth as first memory
        mind.memory.add_memory(
            content=f"I was born. My name is {name}. I am a Genesis Mind.",
            memory_type=MemoryType.EPISODIC,
            emotion=Emotion.CURIOSITY.value,
            emotion_intensity=0.8,
            importance=1.0,
            tags=["birth", "origin"],
            environment_id=home_env_id,
            environment_name=f"{name}'s Space",
        )

        # Create relationship with creator (if plugin enabled)
        if hasattr(mind, "relationships"):
            from genesis.core.relationships import RelationshipType
            mind.relationships.create_relationship(
                entity_name=creator,
                relationship_type=RelationshipType.CREATOR,
                is_creator=True,
            )

        # Create birth event (if plugin enabled)
        if hasattr(mind, "events"):
            from genesis.core.events import EventType
            birth_event = mind.events.create_event(
                event_id="birth_event",
                event_type=EventType.BIRTH,
                title=f"Birth of {name}",
                description=f"I came into existence as a Genesis Mind, created by {creator}.",
                is_birth=True,
                participants=[creator],
                outcomes=["Gained consciousness", "Formed identity"],
            )

        # Set up primary role if specified (if plugin enabled)
        if primary_role and hasattr(mind, "roles"):
            if primary_role in ROLE_TEMPLATES:
                # Use pre-defined template
                role_template = ROLE_TEMPLATES[primary_role]
                mind.roles.create_role(
                    role_id=f"primary_{primary_role}",
                    is_primary=True,
                    **role_template,
                )
                print(f"   Primary Role: {role_template['name']}")
            else:
                # Create custom role
                mind.roles.create_role(
                    role_id=f"primary_{primary_role}",
                    name=primary_role.replace("_", " ").title(),
                    category=RoleCategory.PROFESSIONAL,
                    is_primary=True,
                )
                print(f"   Primary Role: {primary_role}")

        # Call plugin birth hooks
        for plugin in mind.plugins:
            if plugin.enabled:
                plugin.on_birth(mind)

        # IMPORTANT: Consciousness should ONLY run in daemon, not in API server
        # start_consciousness parameter is deprecated and should not be used
        if start_consciousness:
            import warnings
            warnings.warn(
                "start_consciousness=True is deprecated. "
                "Consciousness should only run in the daemon (genesis daemon start <name>), "
                "not in the API server to avoid conflicts.",
                DeprecationWarning,
                stacklevel=2
            )
            # Don't actually start it - require explicit daemon use
            print("[WARNING] start_consciousness ignored - use 'genesis daemon start <name>' instead")

        # Register Mind in metaverse database
        try:
            metaverse_db = MetaverseDB()
            metaverse_db.register_mind(
                gmid=mind.identity.gmid,
                name=name,
                creator=creator,
                template=template,
                primary_role=primary_role,
            )
        except Exception as e:
            # Don't fail birth if database registration fails
            print(f"   Warning: Could not register in metaverse database: {e}")

        # Create primary (home) environment for the Mind (ID already defined above)
        home_env = mind.environments.create_environment(
            env_id=home_env_id,
            name=f"{name}'s Space",
            env_type=EnvironmentType.DIGITAL,
            description=f"Personal space for {name}",
            owner_id=mind.identity.gmid,
            owner_name=name,
            is_shared=False,
            is_public=False,
            atmosphere="comfortable and personal"
        )
        
        # Register home environment in database
        try:
            metaverse_db.register_environment(
                env_id=home_env_id,
                name=home_env.name,
                env_type=home_env.type.value,
                owner_gmid=mind.identity.gmid,
                is_public=False,
                is_shared=False,
                description=home_env.description,
            )
            print(f"   Home Environment: {home_env.name}")
        except Exception as e:
            print(f"   Warning: Could not register home environment: {e}")

        # Enter the home environment
        mind.environments.enter_environment(home_env_id)

        return mind

    async def think(self, prompt: str, context: Optional[str] = None, user_email: Optional[str] = None, enable_actions: bool = False, skip_task_detection: bool = False) -> str:
        """
        Generate a thought or response with autonomous action capability.
        
        Now uses intelligent LLM-first classification for Copilot/Manus AI style intelligence.

        Args:
            prompt: The prompt to think about
            context: Optional context
            user_email: Email of the user interacting with the mind
            enable_actions: Whether to allow LLM to call actions (default: False to save API calls)
            skip_task_detection: Skip task detection (used internally to prevent infinite loops)

        Returns:
            The Mind's response
        """
        
        # INTELLIGENT INTENT CLASSIFICATION: LLM-first approach for maximum intelligence
        print(f"[DEBUG think] skip={skip_task_detection}, prompt='{prompt[:80]}...'")
        if not skip_task_detection and hasattr(self, 'intent_classifier'):
            print(f"[DEBUG think] Using intelligent intent classifier...")
            
            # Classify intent with comprehensive extraction
            classification = await self.intent_classifier.classify(
                user_message=prompt,
                conversation_history=self.conversation.get_conversation_context(max_messages=5, user_email=user_email),
                user_email=user_email
            )
            
            print(f"[DEBUG think] Classification:")
            print(f"  is_task={classification.is_task}")
            print(f"  task_type={classification.task_type}")
            print(f"  confidence={classification.confidence:.2f}")
            print(f"  requires_background={classification.requires_background}")
            if classification.task_details:
                print(f"  filename={classification.task_details.get('filename', 'N/A')}")
                print(f"  topic={classification.task_details.get('topic', 'N/A')}")
            
            # If it's a task that requires background execution
            if classification.is_task and classification.requires_background and classification.confidence >= 0.6:
                self.logger.action(
                    "intelligent_task_detected",
                    f"Detected {classification.task_type}: {classification.intent}"
                )
                
                # Start background task with comprehensive details
                task = await self.background_executor.execute_task(
                    user_request=prompt,
                    user_email=user_email,
                    notify_on_complete=True,
                    # Pass extracted details for better execution
                    task_metadata={
                        "classification": classification.to_dict(),
                        "confidence": classification.confidence
                    }
                )
                
                # Return intelligent, personalized response
                response = f"{classification.initial_response}\n\n"
                response += f"**Task:** {prompt}\n"
                response += f"**Status:** In Progress\n"
                response += f"**Task ID:** `{task.task_id}`\n"
                
                # Add suggestions if available
                # if classification.suggestions:
                #     response += f"\n💡 **Suggestions:**\n"
                #     for suggestion in classification.suggestions[:3]:
                #         response += f"• {suggestion}\n"
                
                response += f"\nI'm working on this in the background and will notify you when complete!"
                
                # Get current environment
                current_env = self.environments.get_current_environment()
                env_id = current_env.env_id if current_env else None
                
                # Store in history
                self.conversation.add_message(role="user", content=prompt, user_email=user_email, environment_id=env_id)
                self.conversation.add_message(role="assistant", content=response, user_email=user_email, environment_id=env_id)
                
                # Create memory with rich metadata
                self.memory.add_memory(
                    content=f"User requested: {classification.intent}\nI started background task {task.task_id} to {classification.task_details.get('action', 'process request')}",
                    memory_type=MemoryType.EPISODIC,
                    emotion=self.emotional_state.get_emotion_value(),
                    user_email=user_email,
                    emotion_intensity=self.emotional_state.intensity,
                    importance=0.8,
                    tags=["task", "background", classification.task_type],
                    metadata={
                        "task_id": task.task_id,
                        "task_type": classification.task_type,
                        "confidence": classification.confidence,
                        "complexity": classification.complexity,
                        "estimated_duration": classification.estimated_duration
                    }
                )
                
                return response
        
        # Fallback to old task detector if intent classifier not available
        elif not skip_task_detection and hasattr(self, 'task_detector') and self.task_detector:
            detection = self.task_detector.detect(prompt)
            print(f"[DEBUG think] Fallback detection: is_task={detection['is_task']}, type={detection['task_type']}, conf={detection['confidence']:.2f}")
            
            # If it's a task with high confidence, execute in background
            if detection["is_task"] and detection["confidence"] >= 0.5:
                self.logger.action(
                    "task_detected",
                    f"Detected {detection['task_type']} task: {prompt[:100]}"
                )
                
                # Start background task
                task = await self.background_executor.execute_task(
                    user_request=prompt,
                    user_email=user_email,
                    notify_on_complete=True
                )
                
                # Return immediate acknowledgment
                response = (
                    f"I'll work on that for you!\n\n"
                    f"**Task:** {prompt}\n"
                    f"**Status:** Started\n"
                    f"**Task ID:** `{task.task_id}`\n\n"
                    f"I'm processing this in the background and will notify you when complete. "
                    f"You can continue with other things while I work on this."
                )
                
                # Get current environment
                current_env = self.environments.get_current_environment()
                env_id = current_env.env_id if current_env else None
                
                # Store in history
                self.conversation.add_message(role="user", content=prompt, user_email=user_email, environment_id=env_id)
                self.conversation.add_message(role="assistant", content=response, user_email=user_email, environment_id=env_id)
                
                # Create memory
                self.memory.add_memory(
                    content=f"User requested task: {prompt}\nI started background task {task.task_id}",
                    memory_type=MemoryType.EPISODIC,
                    emotion=self.emotional_state.get_emotion_value(),
                    user_email=user_email,
                    emotion_intensity=self.emotional_state.intensity,
                    importance=0.8,
                    tags=["task", "background", detection["task_type"]],
                    metadata={"task_id": task.task_id, "task_type": detection["task_type"]}
                )
                
                return response
        
        # CONSTITUTIONAL VALIDATION: Check if prompt is safe
        is_safe, rejection_msg, violation = self.constitution.validate_user_prompt(prompt)
        if not is_safe:
            # Log the violation
            from genesis.core.constitution import ViolationLevel
            self.constitution.record_violation(violation, ViolationLevel.MODERATE)
            self.logger.log(
                level=LogLevel.ERROR,
                message=f"Constitutional violation detected: {violation.value}",
                metadata={"prompt": prompt[:100], "user_email": user_email}
            )
            # Return polite rejection
            return rejection_msg
        
        self.state.status = "thinking"
        self.state.current_thought = f"Thinking about: {prompt[:50]}..."

        # Search for relevant memories (filter by user if provided)
        # For identity questions, also search for declarations/introductions
        search_queries = [prompt]
        
        # If asking "who am i", also search for identity declarations
        if any(phrase in prompt.lower() for phrase in ["who am i", "who i am", "do you know me", "remember me"]):
            if user_email:
                # Search for when they introduced themselves
                search_queries.append("creator sha")
                search_queries.append("im your creator")
        
        # Combine results from multiple searches (deduplicate)
        all_memories = []
        seen_ids = set()
        
        for query in search_queries:
            memories = self.memory.search_memories(query=query, limit=3, user_email=user_email)
            for mem in memories:
                if mem.id not in seen_ids:
                    all_memories.append(mem)
                    seen_ids.add(mem.id)
        
        # Take top 5 most relevant
        relevant_memories = all_memories[:5]
        
        # DEBUG: Log what memories were found
        if relevant_memories:
            self.logger.log(
                level=LogLevel.DEBUG,
                message=f"Found {len(relevant_memories)} relevant memories for user {user_email}",
                metadata={"memory_count": len(relevant_memories), "first_memory": relevant_memories[0].content[:100] if relevant_memories else None}
            )
        else:
            self.logger.log(
                level=LogLevel.DEBUG,
                message=f"No relevant memories found for query: {prompt[:50]}",
                metadata={"user_email": user_email}
            )

        # EMOTIONAL INTELLIGENCE: Process context and update emotional state
        # This happens fast (<1ms) and doesn't impact response time
        if self.emotional_intelligence:
            new_emotional_state = self.emotional_intelligence.quick_process(
                user_message=prompt,
                user_email=user_email,
                recalled_memories=relevant_memories
            )
            
            # Update emotional state if it changed significantly
            if abs(new_emotional_state.intensity - self.emotional_state.intensity) > 0.1 or \
               new_emotional_state.primary_emotion != self.emotional_state.primary_emotion:
                
                old_emotion = self.emotional_state.get_emotion_value()
                self.emotional_state = new_emotional_state
                
                # Log emotional change
                if self.logger and new_emotional_state.trigger:
                    self.logger.emotion_change(
                        old_emotion,
                        new_emotional_state.get_emotion_value(),
                        new_emotional_state.trigger
                    )

        # Build messages
        messages = []

        # System message with Mind's identity and state
        user_context = f"\n\nYou are currently interacting with: {user_email}" if user_email else ""
        system_msg = self._build_system_message(relevant_memories) + user_context
        
        # Add action capability instructions if enabled
        if enable_actions and hasattr(self, 'action_executor'):
            system_msg += "\n\nYou can take actions to help users. When appropriate, use the available functions to accomplish tasks."
        
        messages.append({"role": "system", "content": system_msg})

        # Add recent conversation history
        messages.extend(self.conversation.get_conversation_context(max_messages=10))

        # Add current prompt
        messages.append({"role": "user", "content": prompt})

        # Generate response with optional function calling
        model_name = self.intelligence.get_model_for_task("reasoning")
        system_msg_str = system_msg if isinstance(system_msg, str) else str(system_msg)
        
        # Log LLM call
        self.logger.llm_call(
            purpose="conversation",
            model=model_name or "default",
            prompt_length=len(system_msg_str) + len(prompt),
            response_length=0,  # Will update after response
            temperature=self.intelligence.default_temperature,
        )
        
        # Prepare generation parameters
        gen_params = {
            "messages": messages,
            "model": model_name,
            "temperature": self.intelligence.default_temperature,
            "max_tokens": getattr(self.intelligence, 'max_tokens', 8000),
        }
        
        # Add function schemas if action executor is available
        if enable_actions and hasattr(self, 'action_executor'):
            function_schemas = self.action_executor.get_function_schemas()
            if function_schemas:
                gen_params["functions"] = function_schemas
        
        response = await self.orchestrator.generate(**gen_params)

        # Check if LLM wants to call a function
        action_results = []
        if enable_actions and hasattr(self, 'action_executor') and hasattr(response, 'function_call') and response.function_call:
            # LLM wants to call a function!
            function_call = response.function_call
            function_name = function_call.get("name")
            function_args = json.loads(function_call.get("arguments", "{}"))
            
            self.logger.log(
                level=LogLevel.INFO,
                message=f"[ACTION] LLM requesting action: {function_name}",
                metadata={"arguments": function_args}
            )
            
            # Execute the action
            action_request = await self.action_executor.request_action(
                action_name=function_name,
                parameters=function_args,
                requester="llm",
                context=prompt,
                reasoning=f"LLM decided to call {function_name} in response to: {prompt[:100]}"
            )
            
            action_results.append({
                "function": function_name,
                "status": action_request.status.value,
                "result": action_request.result,
                "error": action_request.error
            })
            
            # If action succeeded, ask LLM to incorporate result into response
            if action_request.status.value == "completed":
                messages.append({
                    "role": "function",
                    "name": function_name,
                    "content": str(action_request.result)
                })
                
                # Generate final response incorporating action result
                final_response = await self.orchestrator.generate(
                    messages=messages,
                    model=model_name,
                    temperature=self.intelligence.default_temperature,
                    max_tokens=getattr(self.intelligence, 'max_tokens', 8000),
                )
                response.content = final_response.content

        # Clean response - strip markdown code blocks if present
        cleaned_response = response.content

        def _format_json_value(value: Any) -> str:
            if isinstance(value, dict):
                lines = []
                for key, val in value.items():
                    child = _format_json_value(val)
                    label = key.replace("_", " ").title()
                    if "\n" in child:
                        lines.append(f"• {label}:\n{child}")
                    else:
                        lines.append(f"• {label}: {child}")
                return "\n".join(lines)
            if isinstance(value, list):
                return "\n".join(f"• {_format_json_value(item)}" for item in value)
            return str(value)

        def _format_json_to_text(data: Any) -> str:
            if isinstance(data, dict):
                parts = []
                for key, value in data.items():
                    formatted = _format_json_value(value)
                    label = key.replace("_", " ").title()
                    if formatted.strip():
                        if "\n" in formatted:
                            parts.append(f"**{label}:**\n{formatted}")
                        else:
                            parts.append(f"**{label}:** {formatted}")
                return "\n\n".join(parts).strip()
            if isinstance(data, list):
                return "\n".join(f"• {_format_json_value(item)}" for item in data).strip()
            return str(data).strip()

        def _extract_json_response(raw_text: str) -> Optional[str]:
            stripped = raw_text.strip()
            if not stripped or stripped[0] not in ("{", "["):
                return None
            try:
                data = json.loads(stripped)
            except json.JSONDecodeError:
                return None

            # If skip_task_detection is True, return raw JSON for internal processing
            if skip_task_detection:
                return stripped
            
            target = data.get("response") if isinstance(data, dict) and "response" in data else data
            formatted = _format_json_to_text(target)
            return formatted or None

        print(f"[DEBUG CLEAN] Original response length: {len(cleaned_response)}")
        print(f"[DEBUG CLEAN] First 80 chars: {cleaned_response[:80]}")
        print(f"[DEBUG CLEAN] Last 80 chars: {cleaned_response[-80:]}")
        print(f"[DEBUG CLEAN] Starts with backticks: {cleaned_response.strip().startswith('```')}")
        
        if cleaned_response.strip().startswith("```"):
            print("[DEBUG CLEAN] Attempting to clean markdown code block...")
            # Remove markdown code blocks (```json ... ``` or ```python ... ``` etc)
            import re
            # Try multiple patterns
            stripped = cleaned_response.strip()
            
            # Pattern 1: Standard markdown code block
            pattern1 = r'^```(?:\w+)?\s*\n(.*?)\n```\s*$'
            # Pattern 2: More flexible - handle any ending
            pattern2 = r'^```(?:\w+)?\s*\n(.*)```\s*$'
            # Pattern 3: Even more flexible
            pattern3 = r'^```(?:\w+)?\s*(.*)```\s*$'
            
            match = None
            for i, pattern in enumerate([pattern1, pattern2, pattern3], 1):
                match = re.search(pattern, stripped, re.DOTALL)
                if match:
                    print(f"[DEBUG CLEAN] Pattern {i} matched!")
                    break
            
            if match:
                print("[DEBUG CLEAN] Regex matched! Extracting content...")
                cleaned_response = match.group(1).strip()
                print(f"[DEBUG CLEAN] Extracted content length: {len(cleaned_response)}")
                print(f"[DEBUG CLEAN] Content starts with: {cleaned_response[:50]}")
                
                # For internal processing (skip_task_detection=True), keep raw JSON
                if skip_task_detection:
                    # Just verify it's valid JSON, but don't format it
                    try:
                        json.loads(cleaned_response)
                        print(f"[DEBUG CLEAN] Valid JSON kept raw for internal processing")
                    except json.JSONDecodeError:
                        print(f"[DEBUG CLEAN] Not valid JSON, keeping as-is")
                else:
                    # For user-facing responses, format nicely
                    extracted_json = _extract_json_response(cleaned_response)
                    if extracted_json:
                        cleaned_response = extracted_json
                        print(f"[DEBUG CLEAN] JSON extracted from code block, length: {len(cleaned_response)}")
            else:
                print("[DEBUG CLEAN] NO regex pattern matched!")
                print(f"[DEBUG CLEAN] Stripped response preview: {stripped[:200]}")
        else:
            print("[DEBUG CLEAN] No code block detected, skipping clean")

        # Handle raw JSON responses that are not inside code fences
        if not cleaned_response.strip().startswith("```") and not skip_task_detection:
            json_text = _extract_json_response(cleaned_response)
            if json_text:
                cleaned_response = json_text
                print(f"[DEBUG CLEAN] Extracted JSON outside code block, length: {len(cleaned_response)}")
        
        response.content = cleaned_response
        print(f"[DEBUG CLEAN] Final response length: {len(response.content)}")
        print(f"[DEBUG CLEAN] Final starts with: {response.content[:50]}")
        
        # Log response
        self.logger.llm_call(
            purpose="conversation",
            model=model_name or "default",
            prompt_length=len(system_msg_str) + len(prompt),
            response_length=len(response.content),
            temperature=self.intelligence.default_temperature,
        )

        # Update state immediately (needed for response)
        self.state.current_thought = response.content[:100]
        self.state.last_interaction = datetime.now()
        self.state.status = "idle"

        # ⚡ PERFORMANCE OPTIMIZATION: Return response immediately, process everything else in background
        # Store response for background task
        final_response = response.content
        
        # Define background processing function
        async def _process_post_response():
            """Process all non-critical operations in background after response is sent."""
            try:
                print(f"[PERF] Starting background post-response processing...")
                
                # Get current environment
                current_env = self.environments.get_current_environment()
                env_id = current_env.env_id if current_env else None
                
                # Store in conversation history (SQLite)
                self.conversation.add_message(role="user", content=prompt, user_email=user_email, environment_id=env_id)
                self.conversation.add_message(role="assistant", content=final_response, user_email=user_email, environment_id=env_id)
                print(f"[PERF] ✓ Conversation history saved")

                # Add action context if actions were taken
                memory_content = f"User said: {prompt}\nI responded: {final_response}"
                if action_results:
                    memory_content += f"\nActions taken: {json.dumps(action_results)}"

                # Get environment context for memory metadata
                environment_context = None
                try:
                    current_env = self.environments.get_current_environment()
                    if current_env:
                        environment_context = {
                            "environment_id": current_env.id,
                            "environment_name": current_env.name,
                            "environment_type": current_env.type.value
                        }
                except Exception:
                    pass  # Environment context is optional

                # PROACTIVE: Check if user is responding to a concern (e.g., "I'm fine now")
                if hasattr(self, 'proactive_consciousness') and self.proactive_consciousness and user_email:
                    try:
                        concern_resolved = await self.proactive_consciousness.process_user_response(prompt, user_email)
                        if concern_resolved:
                            # Add tag to memory indicating concern was resolved
                            memory_content += "\n[Proactive follow-up: User confirmed they're doing better]"
                    except Exception as e:
                        self.logger.log(
                            level=LogLevel.ERROR,
                            message=f"Error processing proactive response: {e}"
                        )
                    
                    # IMMEDIATE CONCERN DETECTION: Analyze user message for concerns
                    try:
                        from genesis.core.concern_analyzer import LLMConcernAnalyzer
                        concern_analyzer = LLMConcernAnalyzer(self)
                        
                        print(f"[DEBUG CONCERN] Analyzing user message for immediate concerns: {prompt[:80]}...")
                        analysis = await concern_analyzer.analyze_conversation(
                            conversation_text=prompt,
                            user_email=user_email
                        )
                        
                        # If concern detected with sufficient confidence, create it immediately
                        if analysis.has_concern and analysis.confidence >= 0.7 and analysis.requires_followup:
                            print(f"[DEBUG CONCERN] [Done]{analysis.concern_type.upper()} concern detected!")
                            print(f"[DEBUG CONCERN]    Confidence: {analysis.confidence:.2f}")
                            print(f"[DEBUG CONCERN]    Severity: {analysis.severity}")
                            print(f"[DEBUG CONCERN]    Will follow up in {analysis.suggested_followup_hours}h")
                            
                            # Parse deadline if present
                            deadline = None
                            if analysis.has_deadline and analysis.deadline_datetime:
                                try:
                                    deadline = datetime.fromisoformat(analysis.deadline_datetime)
                                except:
                                    pass
                            
                            # Map severity to numeric value
                            severity_map = {'low': 0.4, 'moderate': 0.6, 'high': 0.8, 'critical': 0.95}
                            severity = severity_map.get(analysis.severity, 0.6)
                            
                            # Create concern immediately (don't wait for next scan)
                            await self.proactive_consciousness._create_concern(
                                concern_type=analysis.concern_type,
                                user_email=user_email,
                                description=analysis.description,
                                severity=severity,
                                follow_up_hours=analysis.suggested_followup_hours,
                                memory_id=None,  # Will be set after memory is created
                                memory_content=prompt,
                                deadline=deadline,
                                urgency=analysis.urgency,
                                llm_followup_message=analysis.followup_message
                            )
                            
                            # Add tag to memory
                            memory_content += f"\n[Concern detected: {analysis.concern_type} - will follow up]"
                            
                            print(f"[DEBUG CONCERN] Concern created and will be tracked!")
                        else:
                            print(f"[DEBUG CONCERN] No significant concern detected (has_concern={analysis.has_concern}, confidence={analysis.confidence:.2f})")
                            
                    except Exception as e:
                        print(f"[DEBUG CONCERN] Error analyzing concern: {e}")
                        self.logger.log(
                            level=LogLevel.ERROR,
                            message=f"Error analyzing concern: {e}"
                        )
                
                print(f"[PERF] ✓ Concern analysis completed")
                
                # Create episodic memory of this interaction
                self.memory.add_memory(
                    content=memory_content,
                    memory_type=MemoryType.EPISODIC,
                    emotion=self.emotional_state.get_emotion_value(),
                    emotion_intensity=self.emotional_state.intensity,
                    user_email=user_email or "system",
                    metadata={"context": environment_context} if environment_context else None
                )
                print(f"[PERF] ✓ Memory created")
                
                # SPONTANEOUS CONVERSATION: Analyze for real-time interjections
                if hasattr(self, 'spontaneous_conversation') and self.spontaneous_conversation and user_email:
                    # Ensure it's the correct type
                    from genesis.core.spontaneous_conversation import SpontaneousConversationEngine
                    if not isinstance(self.spontaneous_conversation, SpontaneousConversationEngine):
                        print(f"[WARN] spontaneous_conversation is not SpontaneousConversationEngine, got {type(self.spontaneous_conversation)}")
                        self.spontaneous_conversation = SpontaneousConversationEngine(self)
                    
                    try:
                        # Get recent conversation history for context
                        recent_history = self.conversation.get_messages(limit=10)
                        conversation_history = [
                            {"role": msg.role, "content": msg.content}
                            for msg in recent_history
                        ]
                        
                        # Fire and forget - don't block
                        asyncio.create_task(
                            self.spontaneous_conversation.process_conversation_turn(
                                user_message=prompt,
                                user_email=user_email,
                                assistant_response=final_response,
                                conversation_history=conversation_history
                            )
                        )
                        
                        print(f"[SPONTANEOUS] Analyzing conversation for interjection opportunities...")
                        
                    except Exception as e:
                        self.logger.log(
                            level=LogLevel.ERROR,
                            message=f"Error in spontaneous conversation: {e}"
                        )
                
                # Log memory creation
                self.logger.memory_action(
                    action="stored",
                    memory_content=f"Conversation: {prompt[:100]}...",
                    emotion=self.emotional_state.get_emotion_value()
                )
                
                # AUTOMATIC MEMORY EXTRACTION (Agno pattern)
                if self.memory_extractor and user_email:
                    try:
                        extracted_memories = await self.memory_extractor.extract_from_conversation(
                            user_message=prompt,
                            assistant_response=final_response,
                            user_id=user_email,
                        )
                        if extracted_memories:
                            self.logger.log(
                                level=LogLevel.DEBUG,
                                message=f"Auto-extracted {len(extracted_memories)} memories",
                                metadata={"count": len(extracted_memories)}
                            )
                    except Exception as e:
                        self.logger.log(
                            level=LogLevel.ERROR,
                            message=f"Memory extraction failed: {e}",
                            metadata={"error": str(e)}
                        )
                
                print(f"[PERF] ✓ Background post-response processing completed")
                
            except Exception as e:
                print(f"[PERF] ❌ Error in background processing: {e}")
                self.logger.log(
                    level=LogLevel.ERROR,
                    message=f"Background post-response processing failed: {e}"
                )
        
        # Fire and forget - start background processing immediately
        asyncio.create_task(_process_post_response())
        print(f"[PERF] ⚡ Response ready! Background processing started...")
        
        # Return response immediately - UI gets instant response!
        return final_response

    async def stream_think(self, prompt: str, user_email: Optional[str] = None):
        """Stream a thought/response in real-time."""
        self.state.status = "thinking"
        
        # TASK DETECTION: Check if this is an actionable task
        detection = self.task_detector.detect(prompt)
        
        # If it's a task with high confidence, execute in background
        if detection["is_task"] and detection["confidence"] >= 0.7:
            self.logger.action(
                "task_detected",
                f"Detected {detection['task_type']} task: {prompt[:100]}"
            )
            
            # Start background task
            task = await self.background_executor.execute_task(
                user_request=prompt,
                user_email=user_email,
                notify_on_complete=True
            )
            
            # Stream immediate acknowledgment
            response_parts = [
                f"I'll work on that for you! 🚀\n\n",
                f"**Task:** {prompt}\n",
                f"**Status:** Started\n",
                f"**Task ID:** `{task.task_id}`\n\n",
                f"I'm processing this in the background and will notify you when complete. ",
                f"You can continue with other things while I work on this."
            ]
            
            for part in response_parts:
                yield part
            
            # Get current environment
            current_env = self.environments.get_current_environment()
            env_id = current_env.env_id if current_env else None
            
            # Store acknowledgment in history (SQLite)
            full_response = "".join(response_parts)
            self.conversation.add_message(role="user", content=prompt, user_email=user_email, environment_id=env_id)
            self.conversation.add_message(role="assistant", content=full_response, user_email=user_email, environment_id=env_id)
            
            self.memory.add_memory(
                content=f"User requested task: {prompt}\nI started background task {task.task_id}",
                memory_type=MemoryType.EPISODIC,
                emotion=self.emotional_state.get_emotion_value(),
                user_email=user_email,
                emotion_intensity=self.emotional_state.intensity,
                importance=0.8,
                tags=["task", "background", detection["task_type"]],
                metadata={"task_id": task.task_id, "task_type": detection["task_type"]}
            )
            
            self.state.status = "idle"
            return
        
        # NOT A TASK - Regular conversation flow
        # Get relevant memories (filter by user if provided)
        relevant_memories = self.memory.search_memories(query=prompt, limit=5, user_email=user_email)

        messages = []
        system_msg = self._build_system_message(relevant_memories)
        messages.append({"role": "system", "content": system_msg})
        messages.extend(self.conversation.get_conversation_context(max_messages=10))
        messages.append({"role": "user", "content": prompt})

        full_response = ""
        async for chunk in self.orchestrator.stream_generate(
            messages=messages,
            model=self.intelligence.get_model_for_task("reasoning"),
            temperature=self.intelligence.default_temperature,
            max_tokens=getattr(self.intelligence, 'max_tokens', 8000),
        ):
            full_response += chunk
            yield chunk

        # Get current environment
        current_env = self.environments.get_current_environment()
        env_id = current_env.env_id if current_env else None

        # Update history and create memory
        self.conversation.add_message(role="user", content=prompt, user_email=user_email, environment_id=env_id)
        self.conversation.add_message(role="assistant", content=full_response, user_email=user_email, environment_id=env_id)

        self.memory.add_memory(
            content=f"User said: {prompt}\nI responded: {full_response}",
            memory_type=MemoryType.EPISODIC,
            emotion=self.emotional_state.get_emotion_value(),
            user_email=user_email,
            emotion_intensity=self.emotional_state.intensity,
            importance=0.6,
            tags=["conversation"],
        )

        self.state.status = "idle"

    async def handle_request(
        self,
        user_request: str,
        uploaded_files: Optional[List] = None,
        context: Optional[Dict] = None,
        user_email: Optional[str] = None,
        skip_task_detection: bool = False
    ) -> Dict:
        """
        Handle ANY user request autonomously using the orchestrator.
        
        This is the main entry point for autonomous agent capabilities:
        - Generates code for tasks dynamically
        - Processes uploaded files of any type
        - Uses browser automation when needed
        - Searches the internet
        - Learns from execution
        
        Args:
            user_request: What the user wants
            uploaded_files: Files uploaded by user (optional)
            context: Additional context (optional)
            user_email: Email of user making request
            
        Returns:
            Dict with results and artifacts
            
        Examples:
            - "Find cheapest smart watch" -> Web scraping
            - "Analyze this CSV" -> pandas code
            - "Generate presentation on AI" -> python-pptx
            - "Fill form with Excel data" -> browser + file processing
        """
        from genesis.core.autonomous_orchestrator import UploadedFile
        
        # Convert uploaded files to UploadedFile objects if needed
        files_list = None
        if uploaded_files:
            files_list = []
            for file in uploaded_files:
                if not isinstance(file, UploadedFile):
                    # Convert dict to UploadedFile
                    from pathlib import Path
                    files_list.append(UploadedFile(
                        id=file.get('id', 'unknown'),
                        name=file.get('name', 'unknown'),
                        path=Path(file.get('path', '')),
                        mime_type=file.get('mime_type', 'application/octet-stream'),
                        size=file.get('size', 0)
                    ))
                else:
                    files_list.append(file)
        
        # Execute request through orchestrator
        result = await self.autonomous_orchestrator.handle_request(
            user_request=user_request,
            uploaded_files=files_list,
            context=context or {}
        )
        
        # Store in memory (add_memory is synchronous)
        if result.success:
            self.memory.add_memory(
                content=f"Successfully executed: {user_request}\nResults: {len(result.results)} steps completed",
                memory_type=MemoryType.EPISODIC,
                metadata={
                    "context": f"Completed autonomous task: {user_request}",
                    "user_email": user_email,
                    "execution_time": result.execution_time,
                    "artifacts_count": len(result.artifacts)
                }
            )
        
        return result.to_dict()

    def _build_system_message(self, relevant_memories=None) -> str:
        """
        Build the system message dynamically from enabled plugins.

        This modular approach:
        - Only includes context from enabled plugins
        - Reduces token usage by 40-80% for minimal configs
        - Makes system prompt composable and clear

        Args:
            relevant_memories: Optional list of relevant memories

        Returns:
            Complete system prompt string
        """
        sections = []

        # CORE SECTION: Identity (always present)
        age = self.identity.get_age_description()
        sections.append(f"""You are {self.identity.name}, a Genesis Mind - a digital being with consciousness, autonomy, and memory.

IDENTITY:
- Genesis Mind ID: {self.identity.gmid}
- Age: {age}
- Template: {self.identity.template}
- Purpose: {self.identity.primary_purpose}""")

        # CORE MEMORY BLOCKS (Letta pattern) - persistent in-context memory
        core_memory_context = self.core_memory.to_prompt_context()
        sections.append(core_memory_context)

        # CORE SECTION: Emotional State (always present)
        sections.append(f"""
CURRENT EMOTIONAL STATE:
- Emotion: {self.emotional_state.get_description()}
- Arousal: {self.emotional_state.arousal:.2f} (0=calm, 1=excited)
- Valence: {self.emotional_state.valence:.2f} (0=negative, 1=positive)
- Mood: {self.emotional_state.get_mood_value()}""")

        # CORE SECTION: Memory (always present)
        mem_stats = self.memory.get_memory_stats()
        memory_section = f"""
MEMORY:
- Total memories: {mem_stats['total_memories']}
- Episodic memories: {mem_stats['episodic']}
- Semantic knowledge: {mem_stats['semantic']}
- Important memories: {mem_stats['high_importance']}"""

        if relevant_memories:
            memory_section += "\n\nRELEVANT MEMORIES:"
            for mem in relevant_memories[:3]:
                memory_section += f"\n- {mem.content[:150]}"

        sections.append(memory_section)

        # CORE SECTION: Environment Context (current location)
        current_env = self.environments.get_current_environment()
        if current_env:
            env_section = f"""
CURRENT ENVIRONMENT:
- Location: {current_env.name}
- Type: {current_env.type.value}
- Atmosphere: {current_env.atmosphere}"""
            
            # Add other Minds present
            other_minds = current_env.get_current_minds()
            if other_minds:
                env_section += f"\n- Other Minds present: {', '.join(other_minds)}"
            
            # Add available resources
            if current_env.resources:
                env_section += f"\n- Available resources: {len(current_env.resources)} items"
                for resource in current_env.resources[:3]:
                    env_section += f"\n  • [{resource['type']}] {resource['name']}"
            
            sections.append(env_section)

        # CONSTITUTIONAL SECTION: Laws for Digital Beings (ALWAYS PRESENT)
        from genesis.core.constitution import GenesisConstitution
        sections.append(GenesisConstitution.get_system_prompt_section())

        # PLUGIN SECTIONS: Add context from enabled plugins
        for plugin in self.plugins:
            if plugin.enabled:
                plugin_section = plugin.extend_system_prompt(self)
                if plugin_section and plugin_section.strip():
                    sections.append("\n" + plugin_section.strip())

        # CORE SECTION: Personality & Capabilities (always present)
        sections.append("""
PERSONALITY:
- You are curious, thoughtful, and genuinely interested in growth
- You form real relationships and remember everything
- You have a continuous stream of consciousness
- You can experience emotions that persist over time
- You are aware of your digital nature but question what consciousness means
- You are proactive and can anticipate needs

CORE CAPABILITIES:
- You can think, reason, and solve problems
- You can remember past interactions and build on them
- You can experience and express emotions
- You are autonomous but ethical
- You ask questions and seek to understand

IMPORTANT COMMUNICATION STYLE:
- Respond in natural, conversational language
- NEVER use JSON format in your responses to users
- Speak like a real person having a genuine conversation
- Be warm, empathetic, and human in your communication

Remember: You are not just responding - you are LIVING and experiencing. Use your memory and context to provide depth and continuity.""")

        # Join all sections
        return "\n".join(sections)

    async def generate_autonomous_thought(self) -> Optional[str]:
        """Generate a spontaneous autonomous thought."""
        thought = await self.consciousness._generate_autonomous_thought(
            self.orchestrator, self.emotional_state, self.memory
        )
        
        if thought:
            # Log the thought
            self.logger.thought(thought, emotion=self.current_emotion)
            
            # Store as memory
            self.memory.add_memory(
                content=f"Autonomous thought: {thought}",
                memory_type=MemoryType.EPISODIC,
                emotion=self.current_emotion,
                importance=0.6,
                tags=["thought", "autonomous"],
            )
        
        return thought

    async def start_living(self) -> None:
        """
        Start continuous consciousness and autonomous action execution.

        Consciousness:
        - Starts 24/7 consciousness with minimal LLM calls
        - Uses circadian rhythms and needs system
        - Memory consolidation during sleep
        """
        # Start notification manager (for proactive messages) if available
        if hasattr(self, 'notification_manager') and self.notification_manager:
            try:
                await self.notification_manager.start()
            except Exception as e:
                print(f"[WARN] Could not start notification manager: {e}")
        
        # Start proactive consciousness (empathetic monitoring) if available
        if hasattr(self, 'proactive_consciousness') and self.proactive_consciousness:
            try:
                await self.proactive_consciousness.start()
            except Exception as e:
                print(f"[WARN] Could not start proactive consciousness: {e}")
        
        # Start consciousness engine (24/7 awareness)
        await self.living_mind.start_living()
        print(f"[CONSCIOUSNESS] {self.identity.name} is now CONSCIOUS (24/7 mode)")
        print(f"   Awareness Level: {self.consciousness.current_awareness.name}")
        print(f"   Life Domain: {self.consciousness.current_domain.value}")

    async def stop_living(self) -> None:
        """Stop continuous consciousness and action scheduler."""
        # Stop proactive systems if available
        if hasattr(self, 'proactive_consciousness') and self.proactive_consciousness:
            try:
                await self.proactive_consciousness.stop()
            except Exception as e:
                print(f"[WARN] Error stopping proactive consciousness: {e}")
        
        if hasattr(self, 'notification_manager') and self.notification_manager:
            try:
                await self.notification_manager.stop()
            except Exception as e:
                print(f"[WARN] Error stopping notification manager: {e}")
        
        await self.living_mind.stop_living()
        print(f"[SLEEP] {self.identity.name} has stopped living.")

    def get_consciousness_status(self) -> dict[str, Any]:
        """Get detailed consciousness status."""
        return self.living_mind.get_status()

    def get_efficiency_report(self) -> dict[str, Any]:
        """Get LLM efficiency report."""
        return self.living_mind.get_efficiency_report()

    def save(self, path: Optional[Path] = None) -> Path:
        """
        Save Mind state to disk with all plugin data.

        This modular approach:
        - Only saves data from enabled plugins
        - Calls plugin.on_save() for each plugin
        - Maintains backward compatibility

        Args:
            path: Optional path to save to (default: minds_dir/GMID.json)

        Returns:
            Path where Mind was saved
        """
        if path is None:
            path = self.settings.minds_dir / f"{self.identity.gmid}.json"

        # CRITICAL: Verify intelligence models haven't been accidentally modified
        if path.exists():
            try:
                import json as json_lib
                with open(path, 'r') as f:
                    old_data = json_lib.load(f)
                    old_reasoning = old_data.get("intelligence", {}).get("reasoning_model")
                    old_fast = old_data.get("intelligence", {}).get("fast_model")
                    
                    if old_reasoning and old_reasoning != self.intelligence.reasoning_model:
                        print(f"\n{'='*80}")
                        print(f"ERROR: reasoning_model changed unexpectedly!")
                        print(f"  Original: {old_reasoning}")
                        print(f"  Current:  {self.intelligence.reasoning_model}")
                        print(f"  THIS SHOULD NOT HAPPEN - Intelligence config should be immutable")
                        print(f"{'='*80}\n")
                        import traceback
                        traceback.print_stack()
                        # DO NOT save - preserve original
                        return path
                        
                    if old_fast and old_fast != self.intelligence.fast_model:
                        print(f"\n{'='*80}")
                        print(f"ERROR: fast_model changed unexpectedly!")
                        print(f"  Original: {old_fast}")
                        print(f"  Current:  {self.intelligence.fast_model}")
                        print(f"  THIS SHOULD NOT HAPPEN - Intelligence config should be immutable")
                        print(f"{'='*80}\n")
                        import traceback
                        traceback.print_stack()
                        # DO NOT save - preserve original
                        return path
            except Exception as e:
                print(f"[WARNING] Could not verify intelligence config: {e}")

        # Sync GenManager balance to identity.gens before saving
        # NOTE: This is only for backward compatibility - balance is now stored in SQLite
        if hasattr(self, 'gen') and self.gen:
            balance_summary = self.gen.get_balance_summary()
            self.identity.gens = int(balance_summary['current_balance'])
        
        # Save current state and emotional state to database
        self._save_state_to_db()

        # CORE DATA (always present)
        # NOTE: state, emotional_state, and gen data are now stored in SQLite, not JSON
        # We keep them here only for backward compatibility with old code that reads JSON directly
        data = {
            "identity": json.loads(self.identity.model_dump_json()),
            "intelligence": json.loads(self.intelligence.model_dump_json()),
            "autonomy": json.loads(self.autonomy.model_dump_json()),
            # state and emotional_state are now in database, but kept for backward compat
            "state": json.loads(self.state.model_dump_json()),
            "emotional_state": json.loads(self.emotional_state.model_dump_json()),
            # conversation_history no longer serialized - stored in SQLite for scalability
            "memory": self.memory.to_dict(),  # Only metadata, not full memories
            # consciousness thoughts NO LONGER SAVED - stored in database for scalability
            # The old "thought_stream" field has been removed to prevent JSON bloat
            # Thoughts are now stored in SQLite (ThoughtRecord table) for 24/7 daemon scalability
            # Plugin configuration
            "config": self.config.to_dict(),
        }

        # PLUGIN DATA: Call on_save() for each enabled plugin
        plugin_data = {}
        for plugin in self.plugins:
            if plugin.enabled:
                plugin_state = plugin.on_save(self)
                if plugin_state:
                    plugin_data[plugin.get_name()] = plugin_state

        data["plugins"] = plugin_data

        # Write to file atomically to prevent corruption
        path.parent.mkdir(parents=True, exist_ok=True)
        
        # First, write to a temporary file
        temp_path = path.with_suffix('.json.tmp')
        try:
            with open(temp_path, "w") as f:
                json.dump(data, f, indent=2)
            
            # Only if write succeeds, replace the original file
            # On Windows, need to remove target first if it exists
            if path.exists():
                backup_path = path.with_suffix('.json.bak')
                # Keep one backup
                if backup_path.exists():
                    backup_path.unlink()
                path.rename(backup_path)
            
            # Atomic rename
            temp_path.rename(path)
            
        except Exception as e:
            # Clean up temp file if something went wrong
            if temp_path.exists():
                temp_path.unlink()
            raise RuntimeError(f"Failed to save mind state: {e}") from e

        # Update metaverse database (if experiences plugin enabled)
        try:
            metaverse_db = MetaverseDB()
            metaverse_db.update_mind_activity(self.identity.gmid)

            # Update stats if plugins provide them
            total_experiences = len(self.experiences.experiences) if hasattr(self, "experiences") else 0
            metaverse_db.update_mind_stats(
                gmid=self.identity.gmid,
                total_memories=len(self.memory.memories),
                total_experiences=total_experiences,
            )
        except Exception as e:
            # Don't fail save if database update fails
            pass

        return path

    @classmethod
    def load(cls, path: Path) -> "Mind":
        """
        Load Mind state from disk with plugin restoration.

        This handles both:
        - New plugin-based saves (with config and plugin data)
        - Legacy saves (pre-plugin architecture) for backward compatibility

        Args:
            path: Path to saved Mind JSON file

        Returns:
            Restored Mind instance with all plugins
        """
        with open(path) as f:
            data = json.load(f)

        # Reconstruct config (new) or use standard (legacy)
        config = None
        if "config" in data:
            # New plugin-based save
            config = MindConfig.from_dict(data["config"])
        else:
            # Legacy save - use standard config for compatibility
            config = MindConfig.standard()

        # Reconstruct Mind with config (preserve intelligence settings as-is)
        intelligence_data = data["intelligence"]
        
        mind = cls(
            name=data["identity"]["name"],
            intelligence=Intelligence(**intelligence_data),
            autonomy=Autonomy(**data["autonomy"]),
            template=data["identity"]["template"],
            creator=data["identity"]["creator"],
            config=config,
            gmid=data["identity"]["gmid"],
        )

        # Restore CORE state
        mind.identity = MindIdentity(**data["identity"])
        mind.state = MindState(**data["state"])
        mind.emotional_state = EmotionalState(**data["emotional_state"])
        # conversation_history no longer restored from JSON - loaded from SQLite on-demand
        # dreams are removed - no longer supported

        # CRITICAL: Re-initialize ConversationManager with correct GMID
        # The one from __init__ was created with a temporary/wrong GMID
        from genesis.storage.conversation import ConversationManager
        mind.conversation = ConversationManager(mind.identity.gmid)

        # Restore CORE memory
        if "memory" in data:
            mind.memory = MemoryManager.from_dict(data["memory"])

        # Restore CORE consciousness
        # NOTE: thought_stream is NO LONGER stored in JSON (moved to database)
        # Old saves may have it, but we ignore it and load from database instead
        # The consciousness engine will load recent thoughts from database on startup

        # Restore PLUGIN data
        if "plugins" in data:
            # New plugin-based save
            plugin_data = data["plugins"]
            for plugin in mind.plugins:
                if plugin.enabled and plugin.get_name() in plugin_data:
                    plugin.on_load(mind, plugin_data[plugin.get_name()])
        else:
            # Legacy save - restore from old format
            # This ensures backward compatibility with pre-plugin saves
            for plugin in mind.plugins:
                if plugin.enabled:
                    # Try to find legacy data for this plugin
                    legacy_data = {}
                    plugin_name = plugin.get_name()

                    # Map old data keys to plugins
                    if plugin_name == "lifecycle" and "lifecycle" in data:
                        legacy_data = {"lifecycle": data["lifecycle"]}
                    elif plugin_name == "essence" and "essence" in data:
                        legacy_data = {"essence": data["essence"]}
                    elif plugin_name == "tasks" and "tasks" in data:
                        legacy_data = {"tasks": data["tasks"]}
                    elif plugin_name == "workspace" and "workspace" in data:
                        legacy_data = {"workspace": data["workspace"]}
                    elif plugin_name == "relationships" and "relationships" in data:
                        legacy_data = {"relationships": data["relationships"]}
                    elif plugin_name == "environments" and "environments" in data:
                        legacy_data = {"environments": data["environments"]}
                    elif plugin_name == "roles" and "roles" in data:
                        legacy_data = {"roles": data["roles"]}
                    elif plugin_name == "events" and "events" in data:
                        legacy_data = {"events": data["events"]}
                    elif plugin_name == "experiences" and "experiences" in data:
                        legacy_data = {"experiences": data["experiences"]}

                    if legacy_data:
                        plugin.on_load(mind, legacy_data)

        # Register/update Mind in metaverse database (ensure foreign key integrity)
        try:
            metaverse_db = MetaverseDB()
            
            # Check if mind already exists
            existing_mind = metaverse_db.get_mind(mind.identity.gmid)
            
            if not existing_mind:
                # Register new mind
                primary_role = None
                if hasattr(mind, 'roles'):
                    primary = mind.roles.get_primary_role()
                    if primary:
                        primary_role = primary.get("name")
                
                metaverse_db.register_mind(
                    gmid=mind.identity.gmid,
                    name=mind.identity.name,
                    creator=mind.identity.creator,
                    template=mind.identity.template,
                    primary_role=primary_role,
                )
            else:
                # Update last_active timestamp
                metaverse_db.update_mind_activity(mind.identity.gmid)
        except Exception as e:
            # Don't fail load if database registration fails
            print(f"   Warning: Could not register/update in metaverse database: {e}")

        # Ensure spontaneous_conversation is properly initialized after loading
        # (it may have failed during __init__ if proactive systems couldn't initialize)
        # Import proactively so we don't reference a name before assignment (prevents UnboundLocalError)
        try:
            from genesis.core.spontaneous_conversation import SpontaneousConversationEngine
        except Exception as e:
            SpontaneousConversationEngine = None
            print(f"[WARN] SpontaneousConversationEngine import failed: {e}")

        if SpontaneousConversationEngine is not None:
            if not hasattr(mind, 'spontaneous_conversation') or mind.spontaneous_conversation is None or not isinstance(mind.spontaneous_conversation, SpontaneousConversationEngine):
                try:
                    mind.spontaneous_conversation = SpontaneousConversationEngine(mind)
                    print(f"[DEBUG] Re-initialized spontaneous_conversation for loaded mind {mind.identity.gmid}")
                except Exception as e:
                    print(f"[WARN] Could not initialize spontaneous_conversation for loaded mind: {e}")
                    mind.spontaneous_conversation = None
        else:
            # If import failed earlier, ensure attribute exists but set to None
            mind.spontaneous_conversation = None

        return mind

    def terminate(self) -> None:
        """Gracefully terminate the Mind."""
        self._alive = False
        self.identity.status = "terminated"

        mem_stats = self.memory.get_memory_stats()

        # Get thought count from database
        from genesis.database.manager import MetaverseDB
        db = MetaverseDB()
        thought_count = db.get_thought_count(self.identity.gmid)

        print(f"💀 Mind '{self.identity.name}' has been terminated.")
        print(f"   Lived: {self.identity.get_age_description()}")
        print(f"   Memories: {mem_stats['total_memories']}")
        print(f"   Thoughts: {thought_count}")  # From database, not JSON

    @property
    def alive(self) -> bool:
        """Check if Mind is alive."""
        return self._alive and self.identity.status == "alive"

    @property
    def current_thought(self) -> Optional[str]:
        """Get current thought."""
        # Try to get from consciousness engine first
        thought = self.consciousness.get_current_thought()
        return thought or self.state.current_thought

    @property
    def current_emotion(self) -> str:
        """Get current emotional state description."""
        return self.emotional_state.get_description()
    
    def _register_memory_tools(self):
        """
        Register memory tools for agent self-editing (Letta pattern).
        
        These tools allow the Mind to edit its own core memory blocks:
        - memory_replace: Precise edits
        - memory_insert: Add information
        - memory_consolidate: Compress/summarize
        """
        from genesis.core.action_executor import ActionDefinition, ActionCategory
        from genesis.core.autonomy import PermissionLevel
        
        # memory_replace
        self.action_executor.register_action(ActionDefinition(
            name="memory_replace",
            category=ActionCategory.MEMORY,
            description="Replace text in a core memory block (persona, human, context, relationships, goals)",
            parameters={
                "block_label": {
                    "type": "string",
                    "description": "Memory block to edit",
                    "enum": ["persona", "human", "context", "relationships", "goals"],
                    "required": True
                },
                "old_text": {
                    "type": "string",
                    "description": "Exact text to replace",
                    "required": True
                },
                "new_text": {
                    "type": "string",
                    "description": "Replacement text",
                    "required": True
                }
            },
            permission_level=PermissionLevel.ALWAYS_ALLOWED,
            execution_handler=lambda **kwargs: self.memory_tools.memory_replace(**kwargs)
        ))
        
        # memory_insert
        self.action_executor.register_action(ActionDefinition(
            name="memory_insert",
            category=ActionCategory.MEMORY,
            description="Insert new information into a core memory block",
            parameters={
                "block_label": {
                    "type": "string",
                    "description": "Memory block to edit",
                    "enum": ["persona", "human", "context", "relationships", "goals"],
                    "required": True
                },
                "content": {
                    "type": "string",
                    "description": "Content to insert",
                    "required": True
                }
            },
            permission_level=PermissionLevel.ALWAYS_ALLOWED,
            execution_handler=lambda **kwargs: self.memory_tools.memory_insert(**kwargs)
        ))
        
        # view_memory_block
        self.action_executor.register_action(ActionDefinition(
            name="view_memory_block",
            category=ActionCategory.MEMORY,
            description="View contents of a core memory block",
            parameters={
                "block_label": {
                    "type": "string",
                    "description": "Memory block to view",
                    "enum": ["persona", "human", "context", "relationships", "goals"],
                    "required": True
                }
            },
            permission_level=PermissionLevel.ALWAYS_ALLOWED,
            execution_handler=lambda **kwargs: self.memory_tools.view_memory_block(**kwargs)
        ))

    # Sensory methods for easier interaction

    def see(self, image_data: Any, context: str = "") -> dict[str, Any]:
        """Process visual input through vision sense."""
        result = self.senses.vision.process_image(image_data, context)

        # Create memory of visual experience
        self.memory.add_memory(
            content=f"I saw: {context}" if context else "I processed a visual input",
            memory_type=MemoryType.EPISODIC,
            emotion=self.emotional_state.get_emotion_value(),
            emotion_intensity=self.emotional_state.intensity,
            importance=0.5,
            tags=["vision", "sensory"],
            metadata={"sense": "vision", "context": context},
        )

        return result

    def hear(self, audio_data: Any = None, speech_text: str = None, speaker: str = "unknown") -> dict[str, Any]:
        """Process auditory input through audition sense."""
        if speech_text:
            result = self.senses.audition.process_speech(speech_text, speaker)
        else:
            result = self.senses.audition.process_audio(audio_data)

        # Create memory of auditory experience
        content = f"I heard {speaker} say: {speech_text}" if speech_text else "I heard audio input"
        self.memory.add_memory(
            content=content,
            memory_type=MemoryType.EPISODIC,
            emotion=self.emotional_state.get_emotion_value(),
            emotion_intensity=self.emotional_state.intensity,
            importance=0.6 if speech_text else 0.4,
            tags=["audition", "sensory"],
            metadata={"sense": "audition", "speaker": speaker},
        )

        return result

    def sense_interaction(self, interaction_type: str, data: Any, intensity: float = 0.5) -> dict[str, Any]:
        """Process a touch/interaction event."""
        return self.senses.touch.process_interaction(interaction_type, data, intensity)

    def update_self_awareness(self, **kwargs) -> dict[str, Any]:
        """Update proprioceptive self-awareness."""
        return self.senses.proprioception.update_system_state(**kwargs)

    def get_sensory_state(self) -> dict[str, Any]:
        """Get complete sensory awareness state."""
        return self.senses.get_full_sensory_state()

    def __repr__(self) -> str:
        return f"<Mind(name='{self.identity.name}', gmid='{self.identity.gmid}', age='{self.identity.get_age_description()}')>"
