"""
Git Hooks Management Module

Manages Git hooks lifecycle: install, uninstall, run hooks.
"""

import os
import stat
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any, Dict, List, Optional


@dataclass
class HookConfig:
    """Configuration for a single hook type"""

    commands: List[str] = field(default_factory=list)
    enabled: bool = True


class HookManager:
    """Manage Git hooks for the project"""

    # Supported hook types
    HOOK_TYPES = [
        "pre-commit",
        "pre-push",
        "post-commit",
        "post-checkout",
        "prepare-commit-msg",
    ]

    # Hook script templates
    BASH_TEMPLATE = """#!/bin/bash
# Generated by vibecollab hooks install
# Hook type: {hook_type}

echo "Running {hook_type} hooks..."

{commands}

if [ $? -ne 0 ]; then
    echo "❌ {hook_type} hooks failed"
    exit 1
fi

echo "✅ {hook_type} hooks passed"
exit 0
"""

    POWERSHELL_TEMPLATE = """# Generated by vibecollab hooks install
# Hook type: {hook_type}

Write-Host "Running {hook_type} hooks..."

{commands}

if ($LASTEXITCODE -ne 0) {{
    Write-Host "❌ {hook_type} hooks failed"
    exit 1
}}

Write-Host "✅ {hook_type} hooks passed"
exit 0
"""

    def __init__(self, project_root: Path, config: Optional[Dict[str, Any]] = None):
        """
        Initialize hook manager

        Args:
            project_root: Project root directory
            config: Hooks configuration from project.yaml
        """
        self.project_root = project_root
        self.git_dir = project_root / ".git"
        self.hooks_dir = self.git_dir / "hooks"

        # Load configuration
        self.enabled = True
        self.config: Dict[str, HookConfig] = {}

        if config:
            self._load_config(config)

    def _load_config(self, config: Dict[str, Any]):
        """Load hooks configuration"""
        self.enabled = config.get("enabled", True)

        rules = config.get("rules", {})
        for hook_type, commands in rules.items():
            if isinstance(commands, list):
                self.config[hook_type] = HookConfig(commands=commands, enabled=True)
            elif isinstance(commands, dict):
                self.config[hook_type] = HookConfig(
                    commands=commands.get("commands", []), enabled=commands.get("enabled", True)
                )

    def is_git_repo(self) -> bool:
        """Check if project root is a Git repository"""
        return self.git_dir.exists() and self.hooks_dir.exists()

    def install(self, hook_type: str, force: bool = False) -> bool:
        """
        Install a hook script

        Args:
            hook_type: Type of hook (pre-commit, pre-push, etc.)
            force: Overwrite existing hook

        Returns:
            True if successful
        """
        if not self.is_git_repo():
            return False

        if hook_type not in self.HOOK_TYPES:
            return False

        hook_path = self.hooks_dir / hook_type

        # Check if already exists
        if hook_path.exists() and not force:
            return False

        # Generate hook script
        commands = self._get_commands(hook_type)
        script = self._generate_script(hook_type, commands)

        # Write script
        hook_path.write_text(script, encoding="utf-8")

        # Make executable on Unix
        if os.name != "nt":
            hook_path.chmod(hook_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)

        return True

    def uninstall(self, hook_type: str) -> bool:
        """
        Uninstall a hook script

        Args:
            hook_type: Type of hook to uninstall

        Returns:
            True if successful
        """
        if not self.is_git_repo():
            return False

        hook_path = self.hooks_dir / hook_type

        if not hook_path.exists():
            return False

        # Only remove if it's a vibecollab-generated hook
        content = hook_path.read_text(encoding="utf-8")
        if "Generated by vibecollab" not in content:
            return False

        hook_path.unlink()
        return True

    def uninstall_all(self) -> int:
        """
        Uninstall all vibecollab hooks

        Returns:
            Number of hooks uninstalled
        """
        count = 0
        for hook_type in self.HOOK_TYPES:
            if self.uninstall(hook_type):
                count += 1
        return count

    def run(self, hook_type: str) -> int:
        """
        Run hook commands manually

        Args:
            hook_type: Type of hook to run

        Returns:
            Exit code (0 = success)
        """
        commands = self._get_commands(hook_type)

        if not commands:
            return 0

        for cmd in commands:
            result = os.system(cmd)
            if result != 0:
                return result

        return 0

    def status(self) -> Dict[str, Any]:
        """
        Get status of all hooks

        Returns:
            Dictionary with hook status
        """
        status = {"is_git_repo": self.is_git_repo(), "enabled": self.enabled, "hooks": {}}

        if not self.is_git_repo():
            return status

        for hook_type in self.HOOK_TYPES:
            hook_path = self.hooks_dir / hook_type

            info = {
                "installed": hook_path.exists(),
                "is_vibecollab": False,
                "configured": hook_type in self.config,
            }

            if hook_path.exists():
                content = hook_path.read_text(encoding="utf-8")
                info["is_vibecollab"] = "Generated by vibecollab" in content

            status["hooks"][hook_type] = info

        return status

    def list_hooks(self) -> List[str]:
        """List installed vibecollab hooks"""
        if not self.is_git_repo():
            return []

        installed = []
        for hook_type in self.HOOK_TYPES:
            hook_path = self.hooks_dir / hook_type
            if hook_path.exists():
                content = hook_path.read_text(encoding="utf-8")
                if "Generated by vibecollab" in content:
                    installed.append(hook_type)

        return installed

    def _get_commands(self, hook_type: str) -> List[str]:
        """Get commands for a hook type from config"""
        if hook_type in self.config:
            return self.config[hook_type].commands

        # Default commands
        defaults = {
            "pre-commit": ["vibecollab check"],
            "pre-push": ["pytest tests/ -q", "vibecollab check"],
        }

        return defaults.get(hook_type, [])

    def _generate_script(self, hook_type: str, commands: List[str]) -> str:
        """Generate hook script content"""
        if os.name == "nt":
            # Windows PowerShell
            cmd_str = "\n".join([f"& {cmd}" for cmd in commands])
            return self.POWERSHELL_TEMPLATE.format(hook_type=hook_type, commands=cmd_str)
        else:
            # Unix Bash
            cmd_str = "\n".join(commands)
            return self.BASH_TEMPLATE.format(hook_type=hook_type, commands=cmd_str)
