"""
Git integration for version control management
"""
from typing import List, Optional
import asyncio
from pathlib import Path
import aiofiles
import re

class GitManager:
    def __init__(self, workspace_path: str):
        self.workspace_path = Path(workspace_path)
        
    async def init_repo(self) -> bool:
        """Initialize a new git repository"""
        try:
            process = await asyncio.create_subprocess_exec(
                'git', 'init',
                cwd=str(self.workspace_path),
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE
            )
            await process.communicate()
            return process.returncode == 0
        except Exception:
            return False
            
    async def get_status(self) -> List[str]:
        """Get git status"""
        try:
            process = await asyncio.create_subprocess_exec(
                'git', 'status', '--porcelain',
                cwd=str(self.workspace_path),
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE
            )
            stdout, _ = await process.communicate()
            return stdout.decode().splitlines()
        except Exception:
            return []
            
    async def stage_files(self, files: List[str]) -> bool:
        """Stage specific files"""
        try:
            process = await asyncio.create_subprocess_exec(
                'git', 'add', *files,
                cwd=str(self.workspace_path),
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE
            )
            await process.communicate()
            return process.returncode == 0
        except Exception:
            return False
            
    async def stage_all(self) -> bool:
        """Stage all changes"""
        try:
            process = await asyncio.create_subprocess_exec(
                'git', 'add', '.',
                cwd=str(self.workspace_path),
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE
            )
            await process.communicate()
            return process.returncode == 0
        except Exception:
            return False
            
    async def commit(self, message: str) -> bool:
        """Create a commit with the given message"""
        try:
            process = await asyncio.create_subprocess_exec(
                'git', 'commit', '-m', message,
                cwd=str(self.workspace_path),
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE
            )
            await process.communicate()
            return process.returncode == 0
        except Exception:
            return False
            
    async def create_branch(self, branch_name: str) -> bool:
        """Create a new branch"""
        try:
            process = await asyncio.create_subprocess_exec(
                'git', 'checkout', '-b', branch_name,
                cwd=str(self.workspace_path),
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE
            )
            await process.communicate()
            return process.returncode == 0
        except Exception:
            return False
            
    async def switch_branch(self, branch_name: str) -> bool:
        """Switch to an existing branch"""
        try:
            process = await asyncio.create_subprocess_exec(
                'git', 'checkout', branch_name,
                cwd=str(self.workspace_path),
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE
            )
            await process.communicate()
            return process.returncode == 0
        except Exception:
            return False
            
    async def get_current_branch(self) -> Optional[str]:
        """Get the name of the current branch"""
        try:
            process = await asyncio.create_subprocess_exec(
                'git', 'branch', '--show-current',
                cwd=str(self.workspace_path),
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE
            )
            stdout, _ = await process.communicate()
            return stdout.decode().strip()
        except Exception:
            return None
            
    async def get_diff(self) -> str:
        """Get the current diff"""
        try:
            process = await asyncio.create_subprocess_exec(
                'git', 'diff',
                cwd=str(self.workspace_path),
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE
            )
            stdout, _ = await process.communicate()
            return stdout.decode()
        except Exception:
            return ""
            
    async def auto_commit(self, changes: List[str]) -> bool:
        """Automatically create a commit with an appropriate message"""
        try:
            # Stage all changes
            if not await self.stage_all():
                return False
                
            # Generate commit message
            message = self._generate_commit_message(changes)
            
            # Create commit
            return await self.commit(message)
        except Exception:
            return False
            
    def _generate_commit_message(self, changes: List[str]) -> str:
        """Generate an appropriate commit message from changes"""
        if not changes:
            return "Update code"
            
        # Extract the main action
        main_change = changes[0]
        
        # Try to create a semantic commit message
        if re.search(r'feat|feature|add', main_change, re.I):
            prefix = "feat:"
        elif re.search(r'fix|bug|issue', main_change, re.I):
            prefix = "fix:"
        elif re.search(r'test', main_change, re.I):
            prefix = "test:"
        elif re.search(r'refactor|clean|reorganize', main_change, re.I):
            prefix = "refactor:"
        elif re.search(r'doc|docs|documentation', main_change, re.I):
            prefix = "docs:"
        else:
            prefix = "chore:"
            
        # Create message
        message = f"{prefix} {main_change}"
        
        # Add additional changes as bullet points if there are any
        if len(changes) > 1:
            message += "\n\n"
            for change in changes[1:]:
                message += f"- {change}\n"
                
        return message
