"""
Git Integration for Memory-Bank System

Handles automatic memory-bank updates based on git commits and hooks.
"""

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

from .core import MemoryBankUpdater
from .context import ContextManager


logger = logging.getLogger(__name__)


class GitHookManager:
    """Manages git hooks for automatic memory-bank updates."""
    
    def __init__(self, project_root: Optional[str] = None):
        """Initialize with project root directory."""
        self.project_root = Path(project_root) if project_root else Path.cwd()
        self.git_dir = self.project_root / '.git'
        self.hooks_dir = self.git_dir / 'hooks'
        
    def install_post_commit_hook(self) -> bool:
        """Install post-commit git hook for automatic memory-bank updates."""
        try:
            if not self.git_dir.exists():
                logger.error("Not a git repository")
                return False
            
            self.hooks_dir.mkdir(exist_ok=True)
            
            hook_script = '''#!/bin/bash
# Automatic memory-bank update hook
# Generated by circuit-synth memory-bank system

# Get the latest commit hash
COMMIT_HASH=$(git rev-parse HEAD)

# Check if memory-bank system is enabled
if [ -f ".circuit-synth-memory-bank-config.json" ]; then
    echo "🧠 Updating memory-bank for commit $COMMIT_HASH"
    
    # Try to update memory-bank using Python
    python3 -c "
from circuit_synth.memory_bank.git_integration import update_memory_bank_from_commit
success = update_memory_bank_from_commit('$COMMIT_HASH')
exit(0 if success else 1)
" 2>/dev/null || echo "⚠️  Memory-bank update failed (continuing)"
else
    # Memory-bank not enabled, exit silently
    exit 0
fi
'''
            
            hook_file = self.hooks_dir / 'post-commit'
            with open(hook_file, 'w') as f:
                f.write(hook_script)
            
            # Make hook executable
            hook_file.chmod(0o755)
            
            logger.info("Installed post-commit hook for memory-bank updates")
            return True
            
        except Exception as e:
            logger.error(f"Failed to install git hook: {e}")
            return False
    
    def remove_post_commit_hook(self) -> bool:
        """Remove post-commit git hook."""
        try:
            hook_file = self.hooks_dir / 'post-commit'
            if hook_file.exists():
                # Check if it's our hook
                with open(hook_file, 'r') as f:
                    content = f.read()
                
                if 'circuit-synth memory-bank system' in content:
                    hook_file.unlink()
                    logger.info("Removed memory-bank post-commit hook")
                    return True
                else:
                    logger.warning("Post-commit hook exists but not created by memory-bank system")
                    return False
            else:
                logger.info("No post-commit hook to remove")
                return True
                
        except Exception as e:
            logger.error(f"Failed to remove git hook: {e}")
            return False


def update_memory_bank_from_commit(commit_hash: str) -> bool:
    """Update memory-bank files based on a git commit.
    
    This function is called by the git post-commit hook.
    
    Args:
        commit_hash: Git commit hash to analyze
        
    Returns:
        True if update was successful, False otherwise
    """
    try:
        # Get current context to determine which board to update
        context_manager = ContextManager()
        context = context_manager.get_current_context()
        
        if not context:
            # No specific board context, try to auto-detect or update project level
            context_manager.ensure_context()
            context = context_manager.get_current_context()
        
        if context and context.get('current_pcb'):
            # Update specific board memory-bank
            pcb_path = context.get('pcb_path')
            if pcb_path and Path(pcb_path).exists():
                updater = MemoryBankUpdater(pcb_path)
                return updater.update_from_commit(commit_hash)
        else:
            # Update all boards if no specific context
            project_root = Path.cwd()
            pcbs_dir = project_root / 'pcbs'
            
            if pcbs_dir.exists():
                updated_any = False
                for board_dir in pcbs_dir.iterdir():
                    if board_dir.is_dir() and (board_dir / 'memory-bank').exists():
                        updater = MemoryBankUpdater(str(board_dir))
                        if updater.update_from_commit(commit_hash):
                            updated_any = True
                
                return updated_any
        
        return False
        
    except Exception as e:
        logger.error(f"Failed to update memory-bank from commit {commit_hash}: {e}")
        return False


def get_commit_info(commit_hash: str) -> Dict[str, Any]:
    """Get detailed information about a git commit.
    
    Args:
        commit_hash: Git commit hash
        
    Returns:
        Dictionary with commit information
    """
    try:
        # Get commit message
        result = subprocess.run(
            ['git', 'log', '--format=%B', '-n', '1', commit_hash],
            capture_output=True, text=True
        )
        commit_message = result.stdout.strip()
        
        # Get commit author and date
        result = subprocess.run(
            ['git', 'log', '--format=%an|%ae|%ad', '-n', '1', commit_hash],
            capture_output=True, text=True
        )
        author_info = result.stdout.strip().split('|')
        
        # Get changed files
        result = subprocess.run(
            ['git', 'diff', '--name-only', f'{commit_hash}~1', commit_hash],
            capture_output=True, text=True
        )
        changed_files = result.stdout.strip().split('\n') if result.stdout.strip() else []
        
        return {
            'hash': commit_hash,
            'message': commit_message,
            'author_name': author_info[0] if len(author_info) > 0 else 'Unknown',
            'author_email': author_info[1] if len(author_info) > 1 else 'unknown@example.com',
            'date': author_info[2] if len(author_info) > 2 else 'Unknown',
            'changed_files': changed_files
        }
        
    except Exception as e:
        logger.error(f"Failed to get commit info for {commit_hash}: {e}")
        return {
            'hash': commit_hash,
            'message': 'Unknown',
            'author_name': 'Unknown',
            'author_email': 'unknown@example.com', 
            'date': 'Unknown',
            'changed_files': []
        }


def is_git_repository(path: Optional[str] = None) -> bool:
    """Check if the given path is a git repository.
    
    Args:
        path: Path to check (defaults to current directory)
        
    Returns:
        True if it's a git repository, False otherwise
    """
    check_path = Path(path) if path else Path.cwd()
    git_dir = check_path / '.git'
    return git_dir.exists()


def get_current_commit_hash() -> Optional[str]:
    """Get the current commit hash (HEAD).
    
    Returns:
        Current commit hash or None if not in a git repository
    """
    try:
        result = subprocess.run(
            ['git', 'rev-parse', 'HEAD'],
            capture_output=True, text=True
        )
        return result.stdout.strip()
    except Exception:
        return None


def get_recent_commits(count: int = 10) -> list:
    """Get recent commit hashes and messages.
    
    Args:
        count: Number of recent commits to retrieve
        
    Returns:
        List of dictionaries with commit information
    """
    try:
        result = subprocess.run(
            ['git', 'log', '--format=%H|%s', f'-n', str(count)],
            capture_output=True, text=True
        )
        
        commits = []
        for line in result.stdout.strip().split('\n'):
            if '|' in line:
                hash_part, message = line.split('|', 1)
                commits.append({
                    'hash': hash_part,
                    'message': message,
                    'short_hash': hash_part[:7]
                })
        
        return commits
        
    except Exception as e:
        logger.error(f"Failed to get recent commits: {e}")
        return []