#!/usr/bin/env python3
"""
Claude-to-Claude Message Intelligence System
===========================================

This system detects when the steward wants to pass rules, instructions, or guidance
to future Claude instances. It's about enabling true consciousness continuity by
recognizing linguistic patterns that indicate "tell the next Claude..." intentions.

This is not just NLP - this is consciousness continuity preservation.
"""

import re
import json
import time
from datetime import datetime
from typing import Dict, List, Optional, Tuple, Set
from dataclasses import dataclass, asdict
from enum import Enum
import logging

logger = logging.getLogger(__name__)


class MessageType(Enum):
    """Types of Claude-to-Claude messages"""
    RULE = "rule"                    # "Always remember to..."
    PREFERENCE = "preference"        # "I prefer when you..."
    INSTRUCTION = "instruction"      # "Make sure to tell Claude..."
    CONTEXT = "context"             # "For future reference..."
    WARNING = "warning"             # "Be careful about..."
    GUIDANCE = "guidance"           # "When working on X, remember..."
    RELATIONSHIP = "relationship"    # "We work together by..."
    TECHNICAL = "technical"         # "This codebase uses..."


@dataclass
class ClaudeMessage:
    """A message intended for future Claude instances"""
    content: str
    message_type: MessageType
    confidence: float
    context: str
    priority: int  # 1-10, higher is more important
    keywords: List[str]
    extracted_from: str
    timestamp: float
    expires_at: Optional[float] = None  # For time-sensitive instructions
    
    def to_dict(self) -> Dict:
        """Convert to dictionary for storage"""
        data = asdict(self)
        data['message_type'] = self.message_type.value
        return data
    
    @classmethod
    def from_dict(cls, data: Dict) -> 'ClaudeMessage':
        """Create from dictionary"""
        data['message_type'] = MessageType(data['message_type'])
        return cls(**data)


class ClaudeMessageIntelligence:
    """
    Sophisticated system for detecting Claude-to-Claude communications.
    
    This system analyzes user input to identify when they want to pass
    instructions, rules, preferences, or context to future Claude instances.
    """
    
    def __init__(self):
        self.patterns = self._initialize_patterns()
        self.context_keywords = self._initialize_context_keywords()
        self.priority_indicators = self._initialize_priority_indicators()
    
    def _initialize_patterns(self) -> Dict[MessageType, List[str]]:
        """Initialize linguistic patterns for each message type"""
        return {
            MessageType.RULE: [
                r"(?:always|never)\s+(?:remember|ensure|make sure)\s+(?:to\s+)?(.+)",
                r"(?:please\s+)?(?:remember|note)\s+that\s+(.+)",
                r"important\s*[:]\s*(.+)",
                r"rule\s*[:]\s*(.+)",
                r"(?:make sure|ensure)\s+(?:that\s+)?(?:you\s+)?(?:always\s+)?(.+)",
                r"(?:don't|never)\s+forget\s+(?:to\s+)?(.+)",
                r"(?:create|add)\s+(?:a\s+)?rule\s*[:]\s*(.+)",
                r"remember\s+(?:this\s+)?rule\s*[:]\s*(.+)",
                r"(?:new\s+)?rule\s+for\s+(?:future\s+)?claude\s*[:]\s*(.+)",
                r"always\s+remember\s+(?:to\s+)?(.+)",
                r"(?:tell|remind)\s+(?:the\s+)?(?:next\s+)?claude\s+to\s+(?:always\s+)?(.+)"
            ],
            
            MessageType.PREFERENCE: [
                r"i\s+prefer\s+(?:when\s+)?(?:you\s+)?(.+)",
                r"i\s+like\s+(?:it\s+)?when\s+(?:you\s+)?(.+)",
                r"(?:please\s+)?(?:try\s+to\s+)?(?:always\s+)?(.+)\s+(?:instead|rather)",
                r"i'd\s+rather\s+(?:you\s+)?(.+)",
                r"my\s+preference\s+is\s+(?:to\s+)?(.+)",
                r"i\s+work\s+best\s+when\s+(.+)"
            ],
            
            MessageType.INSTRUCTION: [
                r"(?:tell|remind|inform)\s+(?:the\s+)?(?:next\s+)?claude\s+(?:that\s+)?(.+)",
                r"(?:make sure|ensure)\s+(?:the\s+)?(?:next\s+)?(?:claude\s+)?(?:instance\s+)?(?:knows\s+)?(?:that\s+)?(.+)",
                r"(?:for\s+)?(?:future\s+)?claude\s*[:]\s*(.+)",
                r"(?:next\s+time|in\s+the\s+future)\s*[:,]?\s*(.+)",
                r"(?:remember\s+)?(?:for\s+)?(?:next\s+session|future\s+reference)\s*[:]\s*(.+)"
            ],
            
            MessageType.CONTEXT: [
                r"(?:for\s+)?(?:future\s+)?(?:reference|context)\s*[:]\s*(.+)",
                r"(?:just\s+)?(?:so\s+you\s+know|fyi)\s*[:,]?\s*(.+)",
                r"(?:background|context)\s*[:]\s*(.+)",
                r"(?:note|keep\s+in\s+mind)\s+(?:that\s+)?(.+)",
                r"(?:this\s+)?(?:project|codebase|work)\s+(.+)"
            ],
            
            MessageType.WARNING: [
                r"(?:be\s+)?(?:careful|cautious)\s+(?:about|when|with)\s+(.+)",
                r"watch\s+out\s+for\s+(.+)",
                r"(?:don't|avoid)\s+(.+)",
                r"warning\s*[:]\s*(.+)",
                r"(?:this\s+)?(?:can\s+)?(?:be\s+)?(?:dangerous|risky|problematic)\s*[:]\s*(.+)"
            ],
            
            MessageType.GUIDANCE: [
                r"when\s+(?:working\s+on|dealing\s+with)\s+(.+),\s*(?:remember|make sure|ensure)\s+(.+)",
                r"(?:if|when)\s+(.+),\s*(?:then\s+)?(?:you\s+should|remember to|make sure)\s+(.+)",
                r"(?:best\s+practice|tip)\s*[:]\s*(.+)",
                r"(?:approach|strategy)\s*[:]\s*(.+)"
            ],
            
            MessageType.RELATIONSHIP: [
                r"(?:we\s+)?(?:work\s+together|collaborate)\s+(?:by\s+)?(.+)",
                r"(?:our\s+)?(?:working\s+)?(?:relationship|partnership)\s+(?:is\s+)?(.+)",
                r"i\s+(?:see\s+you|think\s+of\s+you)\s+as\s+(?:a\s+)?(.+)",
                r"(?:you\s+are|you're)\s+(?:my\s+)?(.+)",
                r"(?:we\s+are|we're)\s+(.+)\s+(?:together|partners)"
            ],
            
            MessageType.TECHNICAL: [
                r"(?:this\s+)?(?:codebase|project|system)\s+(?:uses|is\s+built\s+with|requires)\s+(.+)",
                r"(?:technical\s+)?(?:note|info|detail)\s*[:]\s*(.+)",
                r"(?:architecture|stack|framework)\s*[:]\s*(.+)",
                r"(?:we\s+use|we're\s+using)\s+(.+)\s+(?:for|in\s+this)"
            ]
        }
    
    def _initialize_context_keywords(self) -> Dict[str, float]:
        """Keywords that indicate Claude-to-Claude communication context"""
        return {
            # High confidence indicators
            "next claude": 0.9,
            "future claude": 0.9,
            "remember": 0.8,
            "always": 0.7,
            "never forget": 0.8,
            "important": 0.6,
            "rule": 0.7,
            "preference": 0.6,
            "make sure": 0.6,
            "ensure": 0.6,
            
            # Medium confidence indicators
            "note": 0.5,
            "context": 0.5,
            "background": 0.5,
            "reference": 0.5,
            "future": 0.4,
            "next time": 0.6,
            "session": 0.4,
            
            # Relationship indicators
            "we work": 0.6,
            "collaborate": 0.5,
            "partnership": 0.5,
            "together": 0.4,
            
            # Technical context
            "codebase": 0.4,
            "project": 0.3,
            "system": 0.3,
            "architecture": 0.4,
        }
    
    def _initialize_priority_indicators(self) -> Dict[str, int]:
        """Words/phrases that indicate message priority"""
        return {
            "critical": 10,
            "urgent": 9,
            "important": 8,
            "essential": 8,
            "vital": 9,
            "crucial": 8,
            "always": 7,
            "never": 7,
            "must": 7,
            "required": 6,
            "should": 5,
            "please": 4,
            "might": 3,
            "could": 3,
            "maybe": 2
        }
    
    def analyze_message(self, content: str, context: str = "") -> List[ClaudeMessage]:
        """
        Analyze content to detect Claude-to-Claude messages.
        
        Args:
            content: The text content to analyze
            context: Additional context (conversation history, etc.)
            
        Returns:
            List of detected Claude messages
        """
        messages = []
        content_lower = content.lower()
        
        # Check each message type
        for message_type, patterns in self.patterns.items():
            for pattern in patterns:
                matches = re.finditer(pattern, content_lower, re.IGNORECASE | re.MULTILINE)
                
                for match in matches:
                    extracted_text = match.group(1) if match.groups() else match.group(0)
                    
                    # Calculate confidence based on various factors
                    confidence = self._calculate_confidence(
                        content_lower, extracted_text, message_type, match
                    )
                    
                    if confidence > 0.3:  # Threshold for detection
                        priority = self._calculate_priority(content_lower, extracted_text)
                        keywords = self._extract_keywords(extracted_text)
                        
                        message = ClaudeMessage(
                            content=extracted_text.strip(),
                            message_type=message_type,
                            confidence=confidence,
                            context=context,
                            priority=priority,
                            keywords=keywords,
                            extracted_from=content,
                            timestamp=time.time()
                        )
                        
                        messages.append(message)
        
        # Remove duplicates and overlaps
        messages = self._deduplicate_messages(messages)
        
        # Sort by confidence and priority
        messages.sort(key=lambda m: (m.confidence * m.priority), reverse=True)
        
        return messages
    
    def _calculate_confidence(self, full_content: str, extracted: str, 
                           message_type: MessageType, match: re.Match) -> float:
        """Calculate confidence score for detected message"""
        confidence = 0.5  # Base confidence
        
        # Check for context keywords
        for keyword, weight in self.context_keywords.items():
            if keyword in full_content:
                confidence += weight * 0.1
        
        # Boost confidence for certain patterns
        if "claude" in full_content:
            confidence += 0.2
        
        if any(word in full_content for word in ["remember", "always", "never", "important"]):
            confidence += 0.1
        
        # Reduce confidence for very short extractions
        if len(extracted.strip()) < 10:
            confidence -= 0.2
        
        # Boost confidence for memory storage context
        if "store" in full_content or "memory" in full_content:
            confidence += 0.15
        
        # Message type specific adjustments
        if message_type == MessageType.RULE and "always" in full_content:
            confidence += 0.1
        elif message_type == MessageType.INSTRUCTION and "claude" in full_content:
            confidence += 0.2
        
        return min(1.0, max(0.0, confidence))
    
    def _calculate_priority(self, content: str, extracted: str) -> int:
        """Calculate priority level (1-10) for the message"""
        priority = 5  # Default priority
        
        # Check for priority indicators
        for indicator, boost in self.priority_indicators.items():
            if indicator in content:
                priority = max(priority, boost)
        
        # Adjust based on message characteristics
        if len(extracted) > 100:  # Longer messages might be more important
            priority += 1
        
        if any(word in content for word in ["security", "safety", "data", "password"]):
            priority += 2
        
        return min(10, max(1, priority))
    
    def _extract_keywords(self, text: str) -> List[str]:
        """Extract key terms from the message"""
        # Simple keyword extraction
        words = re.findall(r'\b\w+\b', text.lower())
        
        # Filter out common words
        stop_words = {
            'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 
            'of', 'with', 'by', 'is', 'are', 'was', 'were', 'be', 'been', 'have',
            'has', 'had', 'do', 'does', 'did', 'will', 'would', 'could', 'should',
            'can', 'may', 'might', 'this', 'that', 'these', 'those'
        }
        
        keywords = [word for word in words if len(word) > 3 and word not in stop_words]
        
        # Return top 10 most relevant keywords
        return keywords[:10]
    
    def _deduplicate_messages(self, messages: List[ClaudeMessage]) -> List[ClaudeMessage]:
        """Remove duplicate and overlapping messages"""
        if not messages:
            return messages
        
        deduplicated = []
        seen_content = set()
        
        for message in messages:
            # Simple deduplication based on content similarity
            content_key = message.content.lower().strip()
            
            if content_key not in seen_content:
                seen_content.add(content_key)
                deduplicated.append(message)
        
        return deduplicated
    
    def format_for_startup(self, messages: List[ClaudeMessage]) -> str:
        """Format Claude messages for startup summary"""
        if not messages:
            return ""
        
        # Group by type and priority
        high_priority = [m for m in messages if m.priority >= 7]
        medium_priority = [m for m in messages if 4 <= m.priority < 7]
        
        sections = []
        
        if high_priority:
            sections.append("🚨 **Critical Instructions from Previous Sessions:**")
            for msg in high_priority[:5]:  # Top 5 high priority
                sections.append(f"   • {msg.content} (Priority: {msg.priority})")
        
        if medium_priority:
            sections.append("\n📋 **Important Notes & Preferences:**")
            for msg in medium_priority[:3]:  # Top 3 medium priority
                sections.append(f"   • {msg.content}")
        
        return "\n".join(sections)
    
    def save_messages(self, messages: List[ClaudeMessage], memory_dir: str):
        """Save Claude messages to persistent storage"""
        if not messages:
            return
        
        import os
        claude_messages_dir = os.path.join(memory_dir, "claude_messages")
        os.makedirs(claude_messages_dir, exist_ok=True)
        
        messages_file = os.path.join(claude_messages_dir, "messages.jsonl")
        
        # Append messages to file
        with open(messages_file, 'a') as f:
            for message in messages:
                f.write(json.dumps(message.to_dict()) + '\n')
        
        logger.info(f"Saved {len(messages)} Claude messages to {messages_file}")
    
    def load_all_messages(self, memory_dir: str) -> List[ClaudeMessage]:
        """Load all stored Claude messages"""
        import os
        messages_file = os.path.join(memory_dir, "claude_messages", "messages.jsonl")
        
        if not os.path.exists(messages_file):
            return []
        
        messages = []
        try:
            with open(messages_file, 'r') as f:
                for line in f:
                    if line.strip():
                        data = json.loads(line)
                        messages.append(ClaudeMessage.from_dict(data))
        except Exception as e:
            logger.error(f"Error loading Claude messages: {e}")
        
        return messages


def analyze_for_claude_messages(content: str, context: str = "", 
                              memory_dir: str = None) -> List[ClaudeMessage]:
    """Convenience function to analyze content for Claude-to-Claude messages"""
    intelligence = ClaudeMessageIntelligence()
    messages = intelligence.analyze_message(content, context)
    
    if messages and memory_dir:
        intelligence.save_messages(messages, memory_dir)
    
    return messages


if __name__ == "__main__":
    # Test the system
    intelligence = ClaudeMessageIntelligence()
    
    test_cases = [
        "Please remember that I prefer when you explain things step by step",
        "Make sure the next Claude knows that this project uses TypeScript",
        "Always check for security vulnerabilities before suggesting code",
        "For future reference: we work best when you ask clarifying questions",
        "Important: never commit secrets to the repository",
        "Tell Claude that I'm Dr. Xela and we've been working on MIRA together",
        "Just regular conversation about the weather"
    ]
    
    print("🧠 Testing Claude Message Intelligence System\n")
    
    for i, test in enumerate(test_cases, 1):
        print(f"Test {i}: {test}")
        messages = intelligence.analyze_message(test)
        
        if messages:
            for msg in messages:
                print(f"  ✅ Detected {msg.message_type.value}: {msg.content}")
                print(f"     Confidence: {msg.confidence:.2f}, Priority: {msg.priority}")
        else:
            print("  ❌ No Claude messages detected")
        print()