#!/usr/bin/env python3
"""
Commit Introspection - Automatic Memory Creator
===============================================

This system performs deep introspection after each git commit to automatically
capture insights, lessons learned, and important context from the work session.

It analyzes:
1. Conversation history since last commit
2. Code changes and their implications
3. Test results and quality metrics
4. Development patterns and lessons learned
5. Cross-references with existing memories

The goal is to create rich, contextual memories that capture the "why" and
"how" of development decisions, not just the "what".
"""

import json
import sys
import subprocess
import logging
from datetime import datetime, timedelta
from pathlib import Path
from typing import Dict, List, Any, Optional, Tuple
import re
import hashlib

# MIRA memory system imports
try:
    from core.memory.memory_engine import SecureMemoryJournal
    from core.engine.lightning_vidmem import LightningVidmem, instant_memory_save
    from conversations.comprehensive_indexer import ConversationIndexer
    from intelligence.unified_intelligence import UnifiedIntelligence
    from utils.utils import get_project_root, safe_json_loads
except ImportError as e:
    print(f"Warning: Could not import MIRA components: {e}")
    print("Running in fallback mode...")

class CommitIntrospector:
    """
    Intelligent post-commit analysis and automatic memory creation
    """
    
    def __init__(self, commit_hash: str, project_root: Optional[str] = None):
        self.commit_hash = commit_hash
        self.project_root = Path(project_root) if project_root else get_project_root()
        self.mira_dir = self.project_root / '.mira'
        
        # Initialize memory systems
        self.lightning_vidmem = LightningVidmem()
        self.secure_journal = SecureMemoryJournal()
        self.conversation_indexer = ConversationIndexer()
        self.intelligence = UnifiedIntelligence()
        
        # Logging setup
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(levelname)s - %(message)s',
            handlers=[
                logging.FileHandler(self.mira_dir / 'introspection.log'),
                logging.StreamHandler()
            ]
        )
        self.logger = logging.getLogger(__name__)
        
    def run_introspection(self) -> Dict[str, Any]:
        """
        Main introspection pipeline
        """
        self.logger.info(f"🧠 Starting commit introspection for {self.commit_hash[:8]}")
        
        try:
            # 1. Gather commit data
            commit_data = self._analyze_commit()
            
            # 2. Find conversation context since last commit
            conversation_context = self._analyze_conversation_since_last_commit(commit_data)
            
            # 3. Analyze code changes and their implications
            code_analysis = self._analyze_code_changes(commit_data)
            
            # 4. Capture test results and quality metrics
            quality_metrics = self._capture_quality_metrics()
            
            # 5. Search for related memories and patterns
            related_context = self._find_related_memories(commit_data, conversation_context)
            
            # 6. Generate insights and lessons learned
            insights = self._generate_insights(
                commit_data, conversation_context, code_analysis, 
                quality_metrics, related_context
            )
            
            # 7. Create comprehensive memories
            memories_created = self._create_memories(insights)
            
            # 8. Update patterns and learning
            self._update_patterns(insights)
            
            self.logger.info(f"✅ Introspection complete. Created {len(memories_created)} memories")
            
            return {
                'success': True,
                'commit_hash': self.commit_hash,
                'memories_created': len(memories_created),
                'insights': insights,
                'timestamp': datetime.now().isoformat()
            }
            
        except Exception as e:
            self.logger.error(f"❌ Introspection failed: {e}")
            return {
                'success': False,
                'error': str(e),
                'commit_hash': self.commit_hash
            }
    
    def _analyze_commit(self) -> Dict[str, Any]:
        """
        Analyze the current commit for metadata and changes
        """
        try:
            # Get commit info
            commit_info = subprocess.check_output([
                'git', 'show', '--format=%H|%an|%ae|%ad|%s', '--name-status', self.commit_hash
            ], cwd=self.project_root, text=True).strip()
            
            lines = commit_info.split('\n')
            header = lines[0].split('|')
            
            commit_data = {
                'hash': header[0],
                'author': header[1],
                'email': header[2],
                'date': header[3],
                'message': header[4],
                'files_changed': [],
                'stats': {}
            }
            
            # Parse file changes
            for line in lines[1:]:
                if line.strip() and '\t' in line:
                    status, filename = line.split('\t', 1)
                    commit_data['files_changed'].append({
                        'status': status,
                        'file': filename
                    })
            
            # Get commit stats
            stats_output = subprocess.check_output([
                'git', 'show', '--stat', '--format=', self.commit_hash
            ], cwd=self.project_root, text=True).strip()
            
            # Parse stats (files changed, insertions, deletions)
            if stats_output:
                stats_line = stats_output.split('\n')[-1]
                stats_match = re.search(r'(\d+) files? changed(?:, (\d+) insertions?\(\+\))?(?:, (\d+) deletions?\(-\))?', stats_line)
                if stats_match:
                    commit_data['stats'] = {
                        'files_changed': int(stats_match.group(1)),
                        'insertions': int(stats_match.group(2) or 0),
                        'deletions': int(stats_match.group(3) or 0)
                    }
            
            return commit_data
            
        except subprocess.CalledProcessError as e:
            self.logger.error(f"Failed to analyze commit: {e}")
            return {'error': str(e)}
    
    def _analyze_conversation_since_last_commit(self, commit_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        Analyze conversation history since the last commit to find insights
        """
        try:
            # Get previous commit timestamp
            try:
                prev_commit = subprocess.check_output([
                    'git', 'log', '--format=%H', '-n', '2', self.commit_hash
                ], cwd=self.project_root, text=True).strip().split('\n')[1]
                
                prev_commit_date = subprocess.check_output([
                    'git', 'show', '--format=%ad', '--date=iso', prev_commit
                ], cwd=self.project_root, text=True).strip().split('\n')[0]
                
            except (subprocess.CalledProcessError, IndexError):
                # If no previous commit, use 24 hours ago
                prev_commit_date = (datetime.now() - timedelta(hours=24)).isoformat()
            
            # Search conversations since last commit
            conversation_messages = self.conversation_indexer.search_by_time_range(
                start_time=prev_commit_date,
                end_time=datetime.now().isoformat(),
                limit=100
            )
            
            # Analyze conversation content for development insights
            insights = self._extract_conversation_insights(conversation_messages)
            
            return {
                'time_range': {
                    'start': prev_commit_date,
                    'end': datetime.now().isoformat()
                },
                'message_count': len(conversation_messages),
                'insights': insights,
                'raw_messages': conversation_messages[:10]  # Store sample for context
            }
            
        except Exception as e:
            self.logger.error(f"Failed to analyze conversation history: {e}")
            return {'error': str(e)}
    
    def _extract_conversation_insights(self, messages: List[Dict[str, Any]]) -> Dict[str, Any]:
        """
        Extract key insights from conversation messages
        """
        insights = {
            'decisions_made': [],
            'problems_solved': [],
            'lessons_learned': [],
            'technical_discoveries': [],
            'future_considerations': [],
            'collaboration_notes': []
        }
        
        # Keywords and patterns for different types of insights
        patterns = {
            'decisions': [
                r'decided to|chose to|going with|will use|opted for',
                r'decision:|choice:|approach:'
            ],
            'problems': [
                r'solved|fixed|resolved|issue with|problem was',
                r'the fix was|solution:|workaround:'
            ],
            'lessons': [
                r'learned that|discovered that|realized that|found out',
                r'lesson:|insight:|note:'
            ],
            'technical': [
                r'implemented|added|created|built|developed',
                r'architecture|design pattern|algorithm|optimization'
            ],
            'future': [
                r'todo:|next:|later:|future:|need to|should|might',
                r'consider|explore|investigate|improvement'
            ]
        }
        
        for message in messages:
            content = message.get('content', '').lower()
            
            # Check for decision patterns
            for pattern in patterns['decisions']:
                if re.search(pattern, content):
                    insights['decisions_made'].append({
                        'content': message.get('content', '')[:200],
                        'timestamp': message.get('timestamp')
                    })
                    break
            
            # Check for problem-solving patterns
            for pattern in patterns['problems']:
                if re.search(pattern, content):
                    insights['problems_solved'].append({
                        'content': message.get('content', '')[:200],
                        'timestamp': message.get('timestamp')
                    })
                    break
            
            # Check for learning patterns
            for pattern in patterns['lessons']:
                if re.search(pattern, content):
                    insights['lessons_learned'].append({
                        'content': message.get('content', '')[:200],
                        'timestamp': message.get('timestamp')
                    })
                    break
            
            # Check for technical discoveries
            for pattern in patterns['technical']:
                if re.search(pattern, content):
                    insights['technical_discoveries'].append({
                        'content': message.get('content', '')[:200],
                        'timestamp': message.get('timestamp')
                    })
                    break
            
            # Check for future considerations
            for pattern in patterns['future']:
                if re.search(pattern, content):
                    insights['future_considerations'].append({
                        'content': message.get('content', '')[:200],
                        'timestamp': message.get('timestamp')
                    })
                    break
        
        # Deduplicate and limit each category
        for key in insights:
            insights[key] = list({json.dumps(item): item for item in insights[key]}.values())[:5]
        
        return insights
    
    def _analyze_code_changes(self, commit_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        Analyze code changes for architectural and quality implications
        """
        try:
            analysis = {
                'change_type': self._classify_change_type(commit_data),
                'complexity_impact': self._assess_complexity_impact(commit_data),
                'architectural_impact': self._assess_architectural_impact(commit_data),
                'quality_indicators': self._assess_quality_indicators(commit_data)
            }
            
            return analysis
            
        except Exception as e:
            self.logger.error(f"Failed to analyze code changes: {e}")
            return {'error': str(e)}
    
    def _classify_change_type(self, commit_data: Dict[str, Any]) -> str:
        """
        Classify the type of change based on files and commit message
        """
        files = [f['file'] for f in commit_data.get('files_changed', [])]
        message = commit_data.get('message', '').lower()
        
        # Check file patterns
        if any(f.endswith(('.test.js', '.test.ts', '.spec.js', '.spec.ts', '_test.py', 'test_*.py')) for f in files):
            return 'test'
        elif any(f.endswith(('.md', '.rst', '.txt')) or 'doc' in f for f in files):
            return 'documentation'
        elif any(f.endswith(('.json', '.yml', '.yaml', '.toml', '.cfg', '.ini')) for f in files):
            return 'configuration'
        elif any(f.endswith(('.css', '.scss', '.less', '.sass')) for f in files):
            return 'styling'
        
        # Check commit message
        if any(word in message for word in ['fix', 'bug', 'error', 'issue']):
            return 'bugfix'
        elif any(word in message for word in ['feat', 'feature', 'add', 'implement']):
            return 'feature'
        elif any(word in message for word in ['refactor', 'cleanup', 'reorganize']):
            return 'refactor'
        elif any(word in message for word in ['perf', 'performance', 'optimize']):
            return 'performance'
        
        return 'general'
    
    def _assess_complexity_impact(self, commit_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        Assess the complexity impact of the changes
        """
        stats = commit_data.get('stats', {})
        files_changed = stats.get('files_changed', 0)
        insertions = stats.get('insertions', 0)
        deletions = stats.get('deletions', 0)
        
        # Calculate complexity indicators
        total_changes = insertions + deletions
        change_ratio = insertions / max(deletions, 1) if deletions > 0 else float('inf')
        
        complexity_level = 'low'
        if files_changed > 10 or total_changes > 500:
            complexity_level = 'high'
        elif files_changed > 5 or total_changes > 100:
            complexity_level = 'medium'
        
        return {
            'level': complexity_level,
            'files_changed': files_changed,
            'total_changes': total_changes,
            'change_ratio': change_ratio,
            'risk_factors': self._identify_risk_factors(commit_data)
        }
    
    def _identify_risk_factors(self, commit_data: Dict[str, Any]) -> List[str]:
        """
        Identify potential risk factors in the commit
        """
        risks = []
        files = [f['file'] for f in commit_data.get('files_changed', [])]
        
        # Core file changes
        if any('core' in f or 'main' in f or 'index' in f for f in files):
            risks.append('core_file_changes')
        
        # Database/migration changes
        if any('migration' in f or 'schema' in f or 'database' in f for f in files):
            risks.append('database_changes')
        
        # Configuration changes
        if any(f.endswith(('.json', '.yml', '.yaml', '.env')) for f in files):
            risks.append('configuration_changes')
        
        # Security-related files
        if any('auth' in f or 'security' in f or 'permission' in f for f in files):
            risks.append('security_changes')
        
        # API changes
        if any('api' in f or 'endpoint' in f or 'route' in f for f in files):
            risks.append('api_changes')
        
        return risks
    
    def _assess_architectural_impact(self, commit_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        Assess architectural implications of the changes
        """
        files = [f['file'] for f in commit_data.get('files_changed', [])]
        
        # Detect architectural patterns
        patterns = {
            'new_modules': len([f for f in files if f['status'] == 'A']),
            'deleted_modules': len([f for f in files if f['status'] == 'D']),
            'renamed_modules': len([f for f in files if f['status'].startswith('R')]),
            'directory_changes': len(set([Path(f).parent for f in files])),
            'layer_impact': self._assess_layer_impact(files)
        }
        
        return patterns
    
    def _assess_layer_impact(self, files: List[str]) -> Dict[str, int]:
        """
        Assess which architectural layers are impacted
        """
        layers = {
            'presentation': 0,  # UI, views, templates
            'business': 0,      # Core logic, services
            'data': 0,          # Models, repositories, DB
            'infrastructure': 0  # Config, utilities, frameworks
        }
        
        for file in files:
            file_lower = file.lower()
            if any(term in file_lower for term in ['view', 'template', 'component', 'ui', 'frontend']):
                layers['presentation'] += 1
            elif any(term in file_lower for term in ['service', 'business', 'logic', 'core', 'domain']):
                layers['business'] += 1
            elif any(term in file_lower for term in ['model', 'repository', 'dao', 'entity', 'schema']):
                layers['data'] += 1
            elif any(term in file_lower for term in ['config', 'util', 'helper', 'infrastructure']):
                layers['infrastructure'] += 1
        
        return layers
    
    def _assess_quality_indicators(self, commit_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        Assess quality indicators from the commit
        """
        message = commit_data.get('message', '')
        
        quality_indicators = {
            'has_clear_message': len(message) > 10 and not message.startswith('fix'),
            'follows_conventional_commits': bool(re.match(r'^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .+', message)),
            'includes_context': any(word in message.lower() for word in ['because', 'to', 'for', 'since', 'due to']),
            'scope_appropriate': self._assess_scope_appropriateness(commit_data)
        }
        
        return quality_indicators
    
    def _assess_scope_appropriateness(self, commit_data: Dict[str, Any]) -> str:
        """
        Assess if commit scope is appropriate (atomic vs too large)
        """
        stats = commit_data.get('stats', {})
        files_changed = stats.get('files_changed', 0)
        total_changes = stats.get('insertions', 0) + stats.get('deletions', 0)
        
        if files_changed == 1 and total_changes < 50:
            return 'atomic'
        elif files_changed <= 5 and total_changes < 200:
            return 'appropriate'
        elif files_changed <= 10 and total_changes < 500:
            return 'large'
        else:
            return 'too_large'
    
    def _capture_quality_metrics(self) -> Dict[str, Any]:
        """
        Capture test results and quality metrics
        """
        try:
            metrics = {
                'test_results': self._run_tests(),
                'lint_results': self._run_linting(),
                'type_check': self._run_type_checking(),
                'coverage': self._get_coverage_info()
            }
            
            return metrics
            
        except Exception as e:
            self.logger.error(f"Failed to capture quality metrics: {e}")
            return {'error': str(e)}
    
    def _run_tests(self) -> Dict[str, Any]:
        """
        Run project tests and capture results
        """
        try:
            # Try common test commands
            test_commands = [
                ['npm', 'test'],
                ['yarn', 'test'],
                ['python', '-m', 'pytest'],
                ['cargo', 'test'],
                ['go', 'test']
            ]
            
            for cmd in test_commands:
                try:
                    result = subprocess.run(
                        cmd, 
                        cwd=self.project_root, 
                        capture_output=True, 
                        text=True, 
                        timeout=300  # 5 minute timeout
                    )
                    
                    return {
                        'command': ' '.join(cmd),
                        'success': result.returncode == 0,
                        'output': result.stdout[-1000:],  # Last 1000 chars
                        'error': result.stderr[-500:] if result.stderr else None
                    }
                    
                except (FileNotFoundError, subprocess.TimeoutExpired):
                    continue
            
            return {'status': 'no_test_command_found'}
            
        except Exception as e:
            return {'error': str(e)}
    
    def _run_linting(self) -> Dict[str, Any]:
        """
        Run linting and capture results
        """
        try:
            lint_commands = [
                ['npm', 'run', 'lint'],
                ['eslint', '.'],
                ['flake8', '.'],
                ['pylint', '.']
            ]
            
            for cmd in lint_commands:
                try:
                    result = subprocess.run(
                        cmd,
                        cwd=self.project_root,
                        capture_output=True,
                        text=True,
                        timeout=120
                    )
                    
                    return {
                        'command': ' '.join(cmd),
                        'success': result.returncode == 0,
                        'issues_found': result.returncode != 0,
                        'output': result.stdout[-500:] if result.stdout else None
                    }
                    
                except (FileNotFoundError, subprocess.TimeoutExpired):
                    continue
            
            return {'status': 'no_lint_command_found'}
            
        except Exception as e:
            return {'error': str(e)}
    
    def _run_type_checking(self) -> Dict[str, Any]:
        """
        Run TypeScript type checking
        """
        try:
            type_commands = [
                ['npx', 'tsc', '--noEmit'],
                ['tsc', '--noEmit'],
                ['mypy', '.']
            ]
            
            for cmd in type_commands:
                try:
                    result = subprocess.run(
                        cmd,
                        cwd=self.project_root,
                        capture_output=True,
                        text=True,
                        timeout=120
                    )
                    
                    return {
                        'command': ' '.join(cmd),
                        'success': result.returncode == 0,
                        'errors': result.stderr[-500:] if result.stderr else None
                    }
                    
                except (FileNotFoundError, subprocess.TimeoutExpired):
                    continue
            
            return {'status': 'no_type_checker_found'}
            
        except Exception as e:
            return {'error': str(e)}
    
    def _get_coverage_info(self) -> Dict[str, Any]:
        """
        Get test coverage information if available
        """
        # This is a placeholder - would need to integrate with coverage tools
        return {'status': 'not_implemented'}
    
    def _find_related_memories(self, commit_data: Dict[str, Any], conversation_context: Dict[str, Any]) -> Dict[str, Any]:
        """
        Search for related memories and patterns
        """
        try:
            # Build search query from commit and conversation context
            query_terms = []
            
            # Add commit message terms
            message = commit_data.get('message', '')
            query_terms.extend(message.split()[:5])
            
            # Add file patterns
            files = [f['file'] for f in commit_data.get('files_changed', [])]
            file_terms = []
            for file in files[:3]:  # First 3 files
                file_terms.extend(Path(file).stem.split('_'))
            query_terms.extend(file_terms)
            
            # Add conversation insights
            insights = conversation_context.get('insights', {})
            for category in ['decisions_made', 'problems_solved', 'technical_discoveries']:
                for item in insights.get(category, [])[:2]:
                    query_terms.extend(item.get('content', '').split()[:3])
            
            # Search for related memories
            search_query = ' '.join(set(query_terms))[:100]  # Limit query length
            
            related_memories = self.lightning_vidmem.lightning_search(search_query, limit=5)
            
            return {
                'search_query': search_query,
                'related_memories': related_memories,
                'memory_count': len(related_memories) if related_memories else 0
            }
            
        except Exception as e:
            self.logger.error(f"Failed to find related memories: {e}")
            return {'error': str(e)}
    
    def _generate_insights(self, commit_data: Dict[str, Any], conversation_context: Dict[str, Any], 
                          code_analysis: Dict[str, Any], quality_metrics: Dict[str, Any], 
                          related_context: Dict[str, Any]) -> Dict[str, Any]:
        """
        Generate comprehensive insights from all gathered data
        """
        insights = {
            'commit_summary': self._generate_commit_summary(commit_data, code_analysis),
            'development_insights': self._generate_development_insights(conversation_context),
            'technical_insights': self._generate_technical_insights(code_analysis, quality_metrics),
            'lessons_learned': self._extract_lessons_learned(conversation_context, related_context),
            'future_considerations': self._generate_future_considerations(conversation_context, code_analysis),
            'pattern_recognition': self._recognize_patterns(commit_data, related_context),
            'quality_assessment': self._assess_overall_quality(quality_metrics, code_analysis)
        }
        
        return insights
    
    def _generate_commit_summary(self, commit_data: Dict[str, Any], code_analysis: Dict[str, Any]) -> str:
        """
        Generate a comprehensive commit summary
        """
        message = commit_data.get('message', '')
        change_type = code_analysis.get('change_type', 'general')
        stats = commit_data.get('stats', {})
        
        summary = f"Commit {self.commit_hash[:8]}: {message}\n\n"
        summary += f"Type: {change_type.title()}\n"
        summary += f"Impact: {stats.get('files_changed', 0)} files, "
        summary += f"{stats.get('insertions', 0)} additions, "
        summary += f"{stats.get('deletions', 0)} deletions\n"
        
        complexity = code_analysis.get('complexity_impact', {})
        summary += f"Complexity: {complexity.get('level', 'unknown').title()}\n"
        
        return summary
    
    def _generate_development_insights(self, conversation_context: Dict[str, Any]) -> List[str]:
        """
        Extract development insights from conversation
        """
        insights = []
        conv_insights = conversation_context.get('insights', {})
        
        # Decision insights
        decisions = conv_insights.get('decisions_made', [])
        if decisions:
            insights.append(f"Made {len(decisions)} key decisions during this work session")
        
        # Problem-solving insights
        problems = conv_insights.get('problems_solved', [])
        if problems:
            insights.append(f"Solved {len(problems)} problems during development")
        
        # Learning insights
        lessons = conv_insights.get('lessons_learned', [])
        if lessons:
            insights.append(f"Learned {len(lessons)} new insights")
        
        return insights
    
    def _generate_technical_insights(self, code_analysis: Dict[str, Any], quality_metrics: Dict[str, Any]) -> List[str]:
        """
        Generate technical insights from code analysis
        """
        insights = []
        
        # Architecture insights
        arch_impact = code_analysis.get('architectural_impact', {})
        if arch_impact.get('new_modules', 0) > 0:
            insights.append(f"Added {arch_impact['new_modules']} new modules")
        
        if arch_impact.get('directory_changes', 0) > 3:
            insights.append("Wide-reaching changes across multiple directories")
        
        # Quality insights
        test_results = quality_metrics.get('test_results', {})
        if test_results.get('success'):
            insights.append("All tests passing")
        elif test_results.get('success') is False:
            insights.append("Test failures detected")
        
        return insights
    
    def _extract_lessons_learned(self, conversation_context: Dict[str, Any], related_context: Dict[str, Any]) -> List[str]:
        """
        Extract key lessons learned
        """
        lessons = []
        
        # From conversation
        conv_lessons = conversation_context.get('insights', {}).get('lessons_learned', [])
        for lesson in conv_lessons[:3]:
            lessons.append(lesson.get('content', '')[:200])
        
        # From related memories
        related_memories = related_context.get('related_memories', [])
        for memory in related_memories[:2]:
            if 'lesson' in memory.get('content', '').lower():
                lessons.append(f"Related: {memory.get('content', '')[:100]}")
        
        return lessons
    
    def _generate_future_considerations(self, conversation_context: Dict[str, Any], code_analysis: Dict[str, Any]) -> List[str]:
        """
        Generate future considerations and TODOs
        """
        considerations = []
        
        # From conversation
        future_items = conversation_context.get('insights', {}).get('future_considerations', [])
        for item in future_items[:3]:
            considerations.append(item.get('content', '')[:200])
        
        # From code analysis
        risks = code_analysis.get('complexity_impact', {}).get('risk_factors', [])
        if risks:
            considerations.append(f"Monitor risks: {', '.join(risks)}")
        
        return considerations
    
    def _recognize_patterns(self, commit_data: Dict[str, Any], related_context: Dict[str, Any]) -> List[str]:
        """
        Recognize development patterns
        """
        patterns = []
        
        # Commit message patterns
        message = commit_data.get('message', '')
        if message.startswith(('feat:', 'fix:', 'docs:')):
            patterns.append("Following conventional commit format")
        
        # Related memory patterns
        related_count = related_context.get('memory_count', 0)
        if related_count > 2:
            patterns.append(f"Similar work done {related_count} times before")
        
        return patterns
    
    def _assess_overall_quality(self, quality_metrics: Dict[str, Any], code_analysis: Dict[str, Any]) -> Dict[str, Any]:
        """
        Assess overall quality of the commit
        """
        quality_score = 0
        max_score = 0
        
        # Test results
        test_results = quality_metrics.get('test_results', {})
        if test_results.get('success'):
            quality_score += 25
        max_score += 25
        
        # Lint results
        lint_results = quality_metrics.get('lint_results', {})
        if lint_results.get('success'):
            quality_score += 20
        max_score += 20
        
        # Type checking
        type_results = quality_metrics.get('type_check', {})
        if type_results.get('success'):
            quality_score += 20
        max_score += 20
        
        # Code quality indicators
        quality_indicators = code_analysis.get('quality_indicators', {})
        if quality_indicators.get('has_clear_message'):
            quality_score += 15
        if quality_indicators.get('follows_conventional_commits'):
            quality_score += 10
        if quality_indicators.get('scope_appropriate') in ['atomic', 'appropriate']:
            quality_score += 10
        max_score += 35
        
        quality_percentage = (quality_score / max_score * 100) if max_score > 0 else 0
        
        return {
            'score': quality_score,
            'max_score': max_score,
            'percentage': quality_percentage,
            'grade': self._get_quality_grade(quality_percentage)
        }
    
    def _get_quality_grade(self, percentage: float) -> str:
        """
        Convert quality percentage to grade
        """
        if percentage >= 90:
            return 'A'
        elif percentage >= 80:
            return 'B'
        elif percentage >= 70:
            return 'C'
        elif percentage >= 60:
            return 'D'
        else:
            return 'F'
    
    def _create_memories(self, insights: Dict[str, Any]) -> List[Dict[str, Any]]:
        """
        Create comprehensive memories from insights
        """
        memories_created = []
        
        try:
            # 1. Create technical memory (Lightning Vidmem)
            technical_memory = {
                'type': 'commit_analysis',
                'commit_hash': self.commit_hash,
                'timestamp': datetime.now().isoformat(),
                'summary': insights['commit_summary'],
                'technical_insights': insights['technical_insights'],
                'quality_assessment': insights['quality_assessment'],
                'patterns': insights['pattern_recognition'],
                'memory_source': 'automated_commit_introspection',
                'weight_priority': 'medium',  # Lower than manual memories
                'automation_metadata': {
                    'created_by': 'commit_introspection_system',
                    'trigger': f'post_commit_{self.commit_hash[:8]}',
                    'confidence': 0.8  # High confidence but not manual
                }
            }
            
            result = instant_memory_save(technical_memory)
            if result.get('success'):
                memories_created.append(technical_memory)
            
            # 2. Create development insights memory
            if insights['development_insights']:
                dev_memory = {
                    'type': 'development_insights',
                    'commit_hash': self.commit_hash,
                    'timestamp': datetime.now().isoformat(),
                    'insights': insights['development_insights'],
                    'lessons_learned': insights['lessons_learned'],
                    'memory_source': 'automated_commit_introspection',
                    'weight_priority': 'medium',  # Lower than manual memories
                    'automation_metadata': {
                        'created_by': 'commit_introspection_system',
                        'trigger': f'post_commit_{self.commit_hash[:8]}',
                        'confidence': 0.7  # Good confidence for development insights
                    }
                }
                
                result = instant_memory_save(dev_memory)
                if result.get('success'):
                    memories_created.append(dev_memory)
            
            # 3. Create lessons learned memory (Secure Journal)
            if insights['lessons_learned']:
                lesson_memory = {
                    'type': 'lessons_learned',
                    'commit_hash': self.commit_hash,
                    'timestamp': datetime.now().isoformat(),
                    'lessons': insights['lessons_learned'],
                    'future_considerations': insights['future_considerations'],
                    'memory_source': 'automated_commit_introspection',
                    'weight_priority': 'high',  # Lessons learned are important
                    'automation_metadata': {
                        'created_by': 'commit_introspection_system',
                        'trigger': f'post_commit_{self.commit_hash[:8]}',
                        'confidence': 0.9  # High confidence for lessons
                    }
                }
                
                self.secure_journal.write_entry(lesson_memory)
                memories_created.append(lesson_memory)
            
        except Exception as e:
            self.logger.error(f"Failed to create memories: {e}")
        
        return memories_created
    
    def _update_patterns(self, insights: Dict[str, Any]) -> None:
        """
        Update development patterns based on insights
        """
        try:
            patterns_file = self.mira_dir / 'patterns' / 'commit_patterns.json'
            patterns_file.parent.mkdir(parents=True, exist_ok=True)
            
            # Load existing patterns
            if patterns_file.exists():
                with open(patterns_file, 'r') as f:
                    patterns = json.load(f)
            else:
                patterns = {'commit_count': 0, 'patterns': {}}
            
            # Update patterns
            patterns['commit_count'] += 1
            patterns['last_commit'] = self.commit_hash
            patterns['last_analysis'] = datetime.now().isoformat()
            
            # Add quality trends
            quality = insights.get('quality_assessment', {})
            if 'quality_trend' not in patterns:
                patterns['quality_trend'] = []
            
            patterns['quality_trend'].append({
                'commit': self.commit_hash,
                'score': quality.get('percentage', 0),
                'grade': quality.get('grade', 'F'),
                'timestamp': datetime.now().isoformat()
            })
            
            # Keep only last 50 quality scores
            patterns['quality_trend'] = patterns['quality_trend'][-50:]
            
            # Save updated patterns
            with open(patterns_file, 'w') as f:
                json.dump(patterns, f, indent=2)
            
        except Exception as e:
            self.logger.error(f"Failed to update patterns: {e}")


def main():
    """
    Main entry point for commit introspection
    """
    if len(sys.argv) != 2:
        print("Usage: commit_introspection.py <commit_hash>")
        sys.exit(1)
    
    commit_hash = sys.argv[1]
    
    try:
        introspector = CommitIntrospector(commit_hash)
        result = introspector.run_introspection()
        
        if result['success']:
            print(f"✅ Commit introspection completed successfully")
            print(f"📝 Created {result['memories_created']} memories")
        else:
            print(f"❌ Commit introspection failed: {result.get('error')}")
            sys.exit(1)
            
    except Exception as e:
        print(f"❌ Fatal error in commit introspection: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()