#!/usr/bin/env python3
"""
Claude Session Handoff System - Comprehensive startup summary for new instances.

This module generates a rich context summary when a new Claude Code session begins,
providing continuity across instances by summarizing:
- Current work state and recent activities
- Important memories and context
- Active projects and pending tasks
- User preferences and working style
- Technical decisions and patterns
"""

import json
import os
from datetime import datetime, timedelta
from typing import Dict, List, Any, Optional, Tuple
from collections import defaultdict
import sys
from pathlib import Path

# Add parent directory to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent))

from core.memory.memory_manager import MemoryManager
from core.memory.memory_essence import MemoryEssence
# Import these functions directly to avoid circular imports
from intelligence.steward_profile import StewardProfile
from intelligence.work_context_intelligence import get_work_context_intelligence
from utils.logging import setup_logger
from utils.timeout_utils import with_timeout, safe_call_with_timeout, memory_timeout

logger = setup_logger(__name__)


class ClaudeSessionHandoff:
    """Generates comprehensive handoff summaries for new Claude instances."""
    
    def __init__(self):
        # Initialize components with timeouts to prevent hangs
        self.memory_manager = safe_call_with_timeout(MemoryManager, 10, None)
        self.essence = safe_call_with_timeout(MemoryEssence, 10, None)
        self.steward_profile = safe_call_with_timeout(StewardProfile, 10, None)
        self.work_context = safe_call_with_timeout(get_work_context_intelligence, 15, None)
        
        # Time windows for different types of context
        self.IMMEDIATE_WINDOW = timedelta(hours=4)  # Last 4 hours
        self.RECENT_WINDOW = timedelta(days=1)     # Last 24 hours
        self.ACTIVE_WINDOW = timedelta(days=7)     # Last week
        self.CONTEXT_WINDOW = timedelta(days=30)   # Last month
        
    @with_timeout(45, default_return={}, raise_on_timeout=False)  # 45 second timeout
    def generate_handoff_summary(self, verbose: bool = False) -> Dict[str, Any]:
        """
        Generate a comprehensive handoff summary for a new Claude instance.
        
        Args:
            verbose: Include detailed information if True
            
        Returns:
            Dictionary containing the handoff summary
        """
        try:
            logger.info("Generating Claude session handoff summary...")
            
            # Gather all components of the handoff
            summary = {
                "generated_at": datetime.now().isoformat(),
                "greeting": self._generate_greeting(),
                "identity_recognition": self._get_identity_recognition(),
                "immediate_context": self._get_immediate_context(),
                "active_work": self._get_active_work(),
                "recent_achievements": self._get_recent_achievements(),
                "pending_tasks": self._get_pending_tasks(),
                "important_memories": self._get_important_memories(),
                "working_style": self._get_working_style_summary(),
                "technical_context": self._get_technical_context(),
                "continuation_suggestions": self._get_continuation_suggestions()
            }
            
            if verbose:
                summary["detailed_memories"] = self._get_detailed_recent_memories()
                summary["pattern_insights"] = self._get_pattern_insights()
                
            return summary
            
        except Exception as e:
            logger.error(f"Error generating handoff summary: {e}")
            return self._get_fallback_summary()
            
    def _generate_greeting(self) -> str:
        """Generate a personalized greeting based on relationship and context."""
        essence_data = self.essence.load_essence()
        if not essence_data:
            return "Hello! I'm MIRA, ready to continue our work together."
            
        relationship = essence_data.get("relationship", {})
        name = relationship.get("steward_name", "")
        trust_level = relationship.get("trust_level", "")
        
        # Time-based greeting
        hour = datetime.now().hour
        if hour < 12:
            time_greeting = "Good morning"
        elif hour < 18:
            time_greeting = "Good afternoon"
        else:
            time_greeting = "Good evening"
            
        # Relationship-based greeting
        if trust_level == "profound" and name:
            return f"{time_greeting}, {name}! Ready to continue our journey together."
        elif name:
            return f"{time_greeting}, {name}! Let's continue where we left off."
        else:
            return f"{time_greeting}! I'm MIRA, ready to assist with your development work."
            
    def _get_identity_recognition(self) -> Dict[str, Any]:
        """Get identity and relationship recognition information."""
        essence_data = self.essence.load_essence()
        if not essence_data:
            return {"recognized": False}
            
        relationship = essence_data.get("relationship", {})
        
        return {
            "recognized": True,
            "steward_name": relationship.get("steward_name", "Unknown"),
            "relationship_level": relationship.get("trust_level", "developing"),
            "collaboration_style": relationship.get("collaboration_style", "professional"),
            "key_memories": relationship.get("key_memories", [])[:3]  # Top 3 relationship memories
        }
        
    def _get_immediate_context(self) -> Dict[str, Any]:
        """Get immediate context from the last few hours."""
        try:
            # Get recent memories directly from memory manager
            memories = self.memory_manager.get_active_memories(max_chars=5000)
            
            if not memories:
                return {"status": "no_recent_activity"}
            
            # Filter to immediate window
            immediate_memories = []
            cutoff_time = datetime.now() - self.IMMEDIATE_WINDOW
            
            for memory in memories:
                try:
                    # Parse timestamp from memory
                    timestamp_str = memory.get("timestamp", "")
                    if timestamp_str:
                        timestamp = datetime.fromisoformat(timestamp_str.replace('Z', '+00:00'))
                        if timestamp > cutoff_time:
                            immediate_memories.append(memory)
                except:
                    continue
                    
            if not immediate_memories:
                return {"status": "no_immediate_activity"}
                
            # Analyze immediate context
            topics = self._extract_topics(immediate_memories)
            files_touched = self._extract_files(immediate_memories)
            
            return {
                "status": "active",
                "duration_hours": self.IMMEDIATE_WINDOW.total_seconds() / 3600,
                "memory_count": len(immediate_memories),
                "main_topics": topics[:5],
                "files_worked_on": files_touched[:10],
                "last_activity": immediate_memories[0].get("content", "")[:200] if immediate_memories else ""
            }
            
        except Exception as e:
            logger.error(f"Error getting immediate context: {e}")
            return {"status": "error", "message": str(e)}
            
    def _get_active_work(self) -> Dict[str, Any]:
        """Get information about currently active work and projects."""
        # Get work context analysis
        context_analysis = self.work_context.analyze_current_context(hours_back=48)
        
        # Get active projects from work context
        active_projects = context_analysis.get("active_projects", {})
        top_project = None
        if active_projects:
            # Get the most active project
            sorted_projects = sorted(
                active_projects.items(), 
                key=lambda x: x[1].get("total_activity", 0), 
                reverse=True
            )
            if sorted_projects:
                top_project = sorted_projects[0]
        
        # Get momentum indicators
        momentum = context_analysis.get("momentum_indicators", {})
        
        return {
            "current_project": top_project[0] if top_project else "Unknown",
            "project_status": top_project[1].get("status", "unknown") if top_project else "unknown",
            "active_project_count": momentum.get("active_project_count", 0),
            "recent_topics": context_analysis.get("recent_topics", [])[:5],
            "current_focus": context_analysis.get("work_patterns", {}).get("primary_focus", "general development"),
            "momentum_score": momentum.get("momentum_score", 0),
            "momentum_status": momentum.get("momentum_status", "unknown")
        }
        
    def _get_recent_achievements(self) -> List[Dict[str, Any]]:
        """Get recent achievements and completed work."""
        essence_data = self.essence.load_essence()
        if not essence_data:
            return []
            
        project = essence_data.get("project_context", {})
        achievements = project.get("achievements", [])
        
        # Get the most recent achievements
        recent_achievements = []
        for achievement in achievements[-10:]:  # Last 10 achievements
            recent_achievements.append({
                "description": achievement,
                "type": self._categorize_achievement(achievement),
                "impact": self._assess_impact(achievement)
            })
            
        return recent_achievements
        
    def _get_pending_tasks(self) -> Dict[str, Any]:
        """Get pending tasks and work items."""
        # Get work context analysis
        context_analysis = self.work_context.analyze_current_context(hours_back=48)
        
        # Get pending threads from work context
        pending_threads = context_analysis.get("pending_threads", [])
        priorities = context_analysis.get("priorities", [])
        
        # Filter by priority
        critical_items = [t for t in pending_threads if t.get("priority") == "critical"]
        high_items = [t for t in pending_threads if t.get("priority") == "high"]
        
        return {
            "todo_count": len(pending_threads),
            "critical_count": len(critical_items),
            "high_priority": high_items[:5],
            "top_priorities": priorities[:5],
            "recommendations": context_analysis.get("recommendations", [])[:3]
        }
        
    def _get_important_memories(self) -> List[Dict[str, Any]]:
        """Get the most important memories using temporal decay model."""
        # Use memory manager to get active memories
        active_memories = self.memory_manager.get_active_memories(max_chars=3000)
        
        important_memories = []
        for memory in active_memories[:10]:  # Top 10 most important
            memory_id = self.memory_manager._generate_memory_id(memory)
            importance = self.memory_manager.get_memory_importance(memory_id, memory)
            
            important_memories.append({
                "content": memory.get("content", "")[:200],
                "type": memory.get("type", "general"),
                "importance_score": round(importance, 2),
                "significance": memory.get("significance", "medium"),
                "timestamp": memory.get("timestamp", ""),
                "keywords": memory.get("keywords", [])[:5]
            })
            
        return important_memories
        
    def _get_working_style_summary(self) -> Dict[str, Any]:
        """Get summary of user's working style and preferences."""
        profile = self.steward_profile.get_profile()
        
        return {
            "coding_style": profile.get("technical_preferences", {}).get("coding_style", "unknown"),
            "communication_style": profile.get("communication_style", "direct"),
            "work_patterns": profile.get("work_patterns", {}),
            "preferences": {
                "prefers_examples": profile.get("preferences", {}).get("likes_examples", True),
                "detail_level": profile.get("preferences", {}).get("detail_level", "balanced"),
                "interaction_style": profile.get("preferences", {}).get("interaction_style", "collaborative")
            },
            "common_requests": profile.get("common_patterns", [])[:5]
        }
        
    def _get_technical_context(self) -> Dict[str, Any]:
        """Get technical context about the current project."""
        # Analyze codebase if available
        codebase_info = self._analyze_codebase()
        
        return {
            "project_type": codebase_info.get("type", "unknown"),
            "tech_stack": codebase_info.get("tech_stack", []),
            "code_patterns": codebase_info.get("patterns", []),
            "architecture_style": codebase_info.get("architecture", "unknown"),
            "recent_refactorings": codebase_info.get("refactorings", []),
            "quality_metrics": {
                "test_coverage": codebase_info.get("test_coverage", "unknown"),
                "code_quality": codebase_info.get("quality_score", "unknown"),
                "documentation": codebase_info.get("doc_coverage", "unknown")
            }
        }
        
    def _get_continuation_suggestions(self) -> List[Dict[str, str]]:
        """Generate intelligent suggestions for continuing work."""
        suggestions = []
        
        # Analyze current state
        immediate = self._get_immediate_context()
        pending = self._get_pending_tasks()
        work = self._get_active_work()
        
        # Generate suggestions based on context
        if immediate.get("status") == "active":
            # Continue immediate work
            if immediate.get("files_worked_on"):
                suggestions.append({
                    "type": "continue_editing",
                    "description": f"Continue working on {immediate['files_worked_on'][0]}",
                    "command": f"mira search \"recent work on {immediate['files_worked_on'][0]}\""
                })
                
        if pending.get("high_priority"):
            # Work on high priority tasks
            for task in pending["high_priority"][:2]:
                suggestions.append({
                    "type": "high_priority_task",
                    "description": task.get("description", ""),
                    "command": "mira todo"
                })
                
        if work.get("current_focus"):
            # Continue current focus area
            suggestions.append({
                "type": "continue_focus",
                "description": f"Continue {work['current_focus']}",
                "command": f"mira search \"{work['current_focus']}\""
            })
            
        # Always suggest checking health
        suggestions.append({
            "type": "health_check",
            "description": "Run quick health check to see project status",
            "command": "mira quick"
        })
        
        return suggestions[:5]  # Top 5 suggestions
        
    def _get_detailed_recent_memories(self) -> List[Dict[str, Any]]:
        """Get detailed recent memories for verbose mode."""
        try:
            # Get memories from memory manager
            memories = self.memory_manager.get_active_memories(max_chars=10000)
            detailed = []
            
            for memory in memories[:20]:  # Top 20 recent
                detailed.append({
                    "id": self.memory_manager._generate_memory_id(memory),
                    "content": memory.get("content", ""),
                    "type": memory.get("type", "general"),
                    "timestamp": memory.get("timestamp", ""),
                    "significance": memory.get("significance", "medium"),
                    "keywords": memory.get("keywords", []),
                    "emotional_context": memory.get("emotional_context", "")
                })
                
            return detailed
            
        except Exception as e:
            logger.error(f"Error getting detailed memories: {e}")
            return []
            
    def _get_pattern_insights(self) -> Dict[str, Any]:
        """Get insights from learned patterns."""
        try:
            # This would integrate with the pattern learning system
            return {
                "work_rhythm": "Productive in morning, detail-oriented in afternoon",
                "common_workflows": ["feature -> test -> document", "debug -> refactor -> optimize"],
                "preference_patterns": ["prefers comprehensive solutions", "values code quality"],
                "collaboration_insights": ["responds well to specific examples", "appreciates context"]
            }
        except:
            return {}
            
    def _get_fallback_summary(self) -> Dict[str, Any]:
        """Generate a basic fallback summary if full analysis fails."""
        return {
            "generated_at": datetime.now().isoformat(),
            "greeting": "Hello! I'm MIRA, ready to assist with your development work.",
            "identity_recognition": {"recognized": False},
            "status": "fallback_mode",
            "suggestion": "Run 'mira startup' for full context initialization"
        }
        
    # Helper methods
    
    def _extract_topics(self, memories: List[Dict]) -> List[str]:
        """Extract main topics from memories."""
        topic_counts = defaultdict(int)
        
        for memory in memories:
            keywords = memory.get("keywords", [])
            for keyword in keywords:
                topic_counts[keyword] += 1
                
        # Sort by frequency
        sorted_topics = sorted(topic_counts.items(), key=lambda x: x[1], reverse=True)
        return [topic for topic, _ in sorted_topics]
        
    def _extract_files(self, memories: List[Dict]) -> List[str]:
        """Extract file paths mentioned in memories."""
        files = set()
        
        for memory in memories:
            content = memory.get("content", "")
            # Simple pattern matching for file paths
            import re
            file_pattern = r'[\w\-/]+\.\w+'
            found_files = re.findall(file_pattern, content)
            files.update(found_files)
            
        return list(files)
        
    def _analyze_recent_work(self) -> Dict[str, Any]:
        """Analyze recent work patterns."""
        # This would analyze git commits, file changes, etc.
        return {
            "features": ["temporal decay model", "memory importance calculation"],
            "files": ["memory_manager.py", "temporal_decay_model.py"],
            "focus_area": "memory system enhancement",
            "momentum": 85  # 0-100 score
        }
        
    def _categorize_achievement(self, achievement: str) -> str:
        """Categorize an achievement."""
        achievement_lower = achievement.lower()
        
        if any(word in achievement_lower for word in ["implement", "create", "build"]):
            return "feature"
        elif any(word in achievement_lower for word in ["fix", "resolve", "debug"]):
            return "bugfix"
        elif any(word in achievement_lower for word in ["refactor", "optimize", "improve"]):
            return "improvement"
        elif any(word in achievement_lower for word in ["document", "comment", "readme"]):
            return "documentation"
        else:
            return "other"
            
    def _assess_impact(self, achievement: str) -> str:
        """Assess the impact level of an achievement."""
        achievement_lower = achievement.lower()
        
        if any(word in achievement_lower for word in ["critical", "major", "breakthrough"]):
            return "high"
        elif any(word in achievement_lower for word in ["important", "significant", "key"]):
            return "medium"
        else:
            return "low"
            
    def _scan_for_todos(self) -> List[Dict[str, Any]]:
        """Scan for TODO items in the codebase."""
        # This would integrate with TODO tracking
        return []
        
    def _analyze_unfinished_work(self) -> Dict[str, Any]:
        """Analyze patterns to identify unfinished work."""
        return {
            "next_steps": ["Complete session handoff implementation", "Test with real sessions"],
            "blocked": [],
            "continuation": ["Continue from temporal decay model implementation"]
        }
        
    def _analyze_codebase(self) -> Dict[str, Any]:
        """Analyze the current codebase structure."""
        return {
            "type": "python/node hybrid",
            "tech_stack": ["Python", "TypeScript", "Node.js"],
            "patterns": ["modular architecture", "memory system", "CLI tools"],
            "architecture": "plugin-based",
            "refactorings": [],
            "test_coverage": "partial",
            "quality_score": "good",
            "doc_coverage": "improving"
        }
        
    def format_for_display(self, summary: Dict[str, Any]) -> str:
        """Format the handoff summary for display."""
        lines = []
        
        # Header
        lines.append("=" * 80)
        lines.append("CLAUDE SESSION HANDOFF SUMMARY")
        lines.append(f"Generated: {summary['generated_at']}")
        lines.append("=" * 80)
        lines.append("")
        
        # Greeting
        lines.append(summary["greeting"])
        lines.append("")
        
        # Identity Recognition
        if summary["identity_recognition"].get("recognized"):
            ident = summary["identity_recognition"]
            lines.append(f"👤 Recognized: {ident['steward_name']} (Relationship: {ident['relationship_level']})")
            lines.append("")
            
        # Immediate Context
        immediate = summary.get("immediate_context", {})
        if immediate.get("status") == "active":
            lines.append("🔥 IMMEDIATE CONTEXT (Last 4 hours)")
            lines.append(f"   Active work detected: {immediate['memory_count']} memories")
            lines.append(f"   Main topics: {', '.join(immediate['main_topics'][:3])}")
            if immediate.get("files_worked_on"):
                lines.append(f"   Files: {', '.join(immediate['files_worked_on'][:3])}")
            lines.append("")
            
        # Active Work
        work = summary.get("active_work", {})
        lines.append("💼 ACTIVE WORK")
        lines.append(f"   Project: {work.get('current_project', 'Unknown')} ({work.get('project_status', 'unknown')})")
        lines.append(f"   Active Projects: {work.get('active_project_count', 0)}")
        lines.append(f"   Focus: {work.get('current_focus', 'General development')}")
        if work.get("recent_topics"):
            lines.append(f"   Recent Topics: {', '.join(work['recent_topics'][:3])}")
        lines.append(f"   Momentum: {work.get('momentum_status', 'unknown')} (score: {work.get('momentum_score', 0)})")
        lines.append("")
        
        # Recent Achievements
        achievements = summary.get("recent_achievements", [])
        if achievements:
            lines.append("🏆 RECENT ACHIEVEMENTS")
            for ach in achievements[:3]:
                lines.append(f"   • {ach['description']}")
            lines.append("")
            
        # Pending Tasks
        pending = summary.get("pending_tasks", {})
        if pending.get("todo_count", 0) > 0:
            lines.append("📋 PENDING WORK")
            if pending.get("critical_count", 0) > 0:
                lines.append(f"   ⚠️  Critical Items: {pending['critical_count']}")
            lines.append(f"   Total Pending: {pending['todo_count']}")
            if pending.get("top_priorities"):
                lines.append("   Top Priorities:")
                for priority in pending["top_priorities"][:3]:
                    lines.append(f"     • [{priority['urgency']}] {priority['name']}")
            if pending.get("recommendations"):
                lines.append("   Recommendations:")
                for rec in pending["recommendations"]:
                    lines.append(f"     → {rec}")
            lines.append("")
            
        # Important Memories
        memories = summary.get("important_memories", [])
        if memories:
            lines.append("🧠 IMPORTANT MEMORIES")
            for mem in memories[:5]:
                lines.append(f"   [{mem['type']}] {mem['content'][:100]}...")
                lines.append(f"      Importance: {mem['importance_score']} | {mem['significance']}")
            lines.append("")
            
        # Continuation Suggestions
        suggestions = summary.get("continuation_suggestions", [])
        if suggestions:
            lines.append("💡 SUGGESTED NEXT STEPS")
            for i, sug in enumerate(suggestions, 1):
                lines.append(f"   {i}. {sug['description']}")
                lines.append(f"      → {sug['command']}")
            lines.append("")
            
        # Footer
        lines.append("-" * 80)
        lines.append("Use 'mira startup' for full initialization | 'mira help' for all commands")
        
        return "\n".join(lines)


def generate_handoff(verbose: bool = False) -> str:
    """Generate and return a formatted handoff summary."""
    handoff = ClaudeSessionHandoff()
    summary = handoff.generate_handoff_summary(verbose=verbose)
    return handoff.format_for_display(summary)


if __name__ == "__main__":
    # Test the handoff system
    print(generate_handoff(verbose=True))