"""Git hook management for AI Commit Generator."""

import os
import shutil
import stat
import subprocess
from pathlib import Path
from typing import Optional

try:
    # Try modern importlib.resources first
    import importlib.resources as pkg_resources

    HAS_IMPORTLIB_RESOURCES = True
except ImportError:
    # Fallback to pkg_resources for older Python versions
    import pkg_resources

    HAS_IMPORTLIB_RESOURCES = False


class GitError(Exception):
    """Git-related errors."""

    pass


class GitHookManager:
    """Manages Git hook installation and configuration."""

    def __init__(self, repo_root: Optional[Path] = None):
        """Initialize Git hook manager.

        Args:
            repo_root: Root directory of Git repository. If None, will auto-detect.
        """
        self.repo_root = repo_root or self._find_repo_root()
        self.hooks_dir = self.repo_root / ".git" / "hooks"
        self.hook_file = self.hooks_dir / "prepare-commit-msg"

    def _find_repo_root(self) -> Path:
        """Find the Git repository root directory."""
        current = Path.cwd()
        while current != current.parent:
            if (current / ".git").exists():
                return current
            current = current.parent
        raise GitError("Not in a Git repository")

    def is_hook_installed(self) -> bool:
        """Check if the AI commit generator hook is installed."""
        if not self.hook_file.exists():
            return False

        # Check if it's our hook by looking for our signature
        try:
            content = self.hook_file.read_text(encoding="utf-8")
            return "ai-commit-generator" in content
        except Exception:
            return False

    def install_hook(self, force: bool = False) -> bool:
        """Install the Git hook.

        Args:
            force: If True, overwrite existing hook without confirmation

        Returns:
            True if hook was installed, False if cancelled

        Raises:
            GitError: If installation fails
        """
        # Create hooks directory if it doesn't exist
        self.hooks_dir.mkdir(parents=True, exist_ok=True)

        # Check if hook already exists
        if self.hook_file.exists() and not force:
            if self.is_hook_installed():
                print("AI commit generator hook is already installed.")
                return True
            else:
                response = input(
                    "A prepare-commit-msg hook already exists. Overwrite? (y/N): "
                )
                if response.lower() != "y":
                    return False

                # Backup existing hook
                backup_file = self.hook_file.with_suffix(".backup")
                shutil.copy2(self.hook_file, backup_file)
                print(f"Existing hook backed up to {backup_file}")

        # Generate hook content
        hook_content = self._generate_hook_content()

        # Write hook file
        try:
            self.hook_file.write_text(hook_content, encoding="utf-8")
            # Make executable
            self.hook_file.chmod(self.hook_file.stat().st_mode | stat.S_IEXEC)
            return True
        except Exception as e:
            raise GitError(f"Failed to install hook: {e}")

    def uninstall_hook(self) -> bool:
        """Uninstall the Git hook.

        Returns:
            True if hook was uninstalled, False if not found
        """
        if not self.hook_file.exists():
            return False

        # Check if it's our hook
        if not self.is_hook_installed():
            print(
                "Found prepare-commit-msg hook, but it's not from ai-commit-generator"
            )
            return False

        try:
            self.hook_file.unlink()
            return True
        except Exception as e:
            raise GitError(f"Failed to uninstall hook: {e}")

    def _generate_hook_content(self) -> str:
        """Generate the Git hook script content."""
        # Try to detect if we're in a virtual environment
        python_cmd = self._get_python_command()

        hook_content = f"""#!/bin/bash
# AI Commit Generator Git Hook
# This hook was automatically generated by ai-commit-generator

set -e

# Exit if this is a merge commit
if [[ "$2" == "merge" ]]; then
    exit 0
fi

# Try to run the Python package
if command -v {python_cmd} &> /dev/null; then
    if {python_cmd} -c "import ai_commit_generator" &> /dev/null; then
        {python_cmd} -m ai_commit_generator.cli generate --output "$1"
        exit 0
    fi
fi

# Fallback: try with different Python commands
for cmd in python3 python; do
    if command -v $cmd &> /dev/null; then
        if $cmd -c "import ai_commit_generator" &> /dev/null; then
            $cmd -m ai_commit_generator.cli generate --output "$1"
            exit 0
        fi
    fi
done

# If we get here, the package is not available
echo "Error: ai-commit-generator package not found"
echo "Please ensure the package is installed in your Python environment"
echo "Install with: pip install ai-commit-generator"
exit 1
"""
        return hook_content

    def _get_python_command(self) -> str:
        """Get the appropriate Python command to use."""
        # Check if we're in a virtual environment
        if os.getenv("VIRTUAL_ENV"):
            venv_python = Path(os.getenv("VIRTUAL_ENV")) / "bin" / "python"
            if venv_python.exists():
                return str(venv_python)

        # Check if we're in a conda environment
        if os.getenv("CONDA_DEFAULT_ENV"):
            try:
                result = subprocess.run(
                    ["which", "python"], capture_output=True, text=True
                )
                if result.returncode == 0:
                    return result.stdout.strip()
            except Exception:
                pass

        # Try to use the same Python that's running this script
        import sys

        return sys.executable

    def install_config_files(self, force: bool = False) -> bool:
        """Install configuration template files.

        Args:
            force: If True, overwrite existing files without confirmation

        Returns:
            True if files were installed, False if cancelled
        """
        config_file = self.repo_root / ".commitgen.yml"
        env_file = self.repo_root / ".env"

        # Install .commitgen.yml
        if not config_file.exists() or force:
            try:
                template_path = self._get_template_path(".commitgen.yml")
                shutil.copy2(template_path, config_file)
                print(f"Configuration template installed: {config_file}")
            except Exception as e:
                print(f"Warning: Could not install config template: {e}")

        # Install .env template (append to existing or create new)
        try:
            template_path = self._get_template_path(".env.example")
            template_content = template_path.read_text(encoding="utf-8")

            if env_file.exists() and not force:
                # Append to existing .env
                with open(env_file, "a", encoding="utf-8") as f:
                    f.write("\n# AI Commit Generator Configuration\n")
                    f.write("# Uncomment and set your API key:\n")
                    f.write("# GROQ_API_KEY=your_key_here\n")
                print(f"Environment template appended to: {env_file}")
            else:
                # Create new .env
                env_file.write_text(template_content, encoding="utf-8")
                print(f"Environment template installed: {env_file}")

        except Exception as e:
            print(f"Warning: Could not install env template: {e}")

        # Update .gitignore
        self._update_gitignore()

        return True

    def _get_template_path(self, filename: str) -> Path:
        """Get path to a template file."""
        try:
            # Try to get from package resources
            if HAS_IMPORTLIB_RESOURCES:
                template_content = (
                    pkg_resources.files("ai_commit_generator") / "templates" / filename
                ).read_text()
            else:
                # Fallback for older pkg_resources
                template_content = pkg_resources.resource_string(
                    "ai_commit_generator", f"templates/{filename}"
                ).decode("utf-8")

            # Write to temporary file
            import tempfile

            temp_file = Path(tempfile.mktemp(suffix=filename))
            temp_file.write_text(template_content, encoding="utf-8")
            return temp_file

        except Exception:
            # Fallback: look for templates in the source directory
            # This is for development/source installations
            current_dir = Path(__file__).parent
            template_path = current_dir.parent.parent / "templates" / filename
            if template_path.exists():
                return template_path

            # Last resort: create minimal template
            return self._create_minimal_template(filename)

    def _create_minimal_template(self, filename: str) -> Path:
        """Create a minimal template file."""
        import tempfile

        temp_file = Path(tempfile.mktemp(suffix=filename))

        if filename == ".commitgen.yml":
            content = """# AI Commit Message Generator Configuration
api:
  provider: groq

commit:
  max_chars: 72
  types: [feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert]

debug:
  enabled: false
"""
        elif filename == ".env.example":
            content = """# AI Commit Generator Configuration
# Uncomment and set your API key:

# Groq (recommended)
# GROQ_API_KEY=your_groq_key_here

# OpenRouter
# OPENROUTER_API_KEY=your_openrouter_key_here

# Cohere
# COHERE_API_KEY=your_cohere_key_here
"""
        else:
            content = f"# Template for {filename}\n"

        temp_file.write_text(content, encoding="utf-8")
        return temp_file

    def _update_gitignore(self) -> None:
        """Update .gitignore to exclude AI commit generator files."""
        gitignore_file = self.repo_root / ".gitignore"

        entries_to_add = ["# AI Commit Generator", ".env", ".commitgen.log"]

        # Read existing .gitignore
        existing_content = ""
        if gitignore_file.exists():
            existing_content = gitignore_file.read_text(encoding="utf-8")

        # Check if entries already exist
        lines_to_add = []
        for entry in entries_to_add:
            if entry not in existing_content:
                lines_to_add.append(entry)

        # Add new entries if needed
        if lines_to_add:
            with open(gitignore_file, "a", encoding="utf-8") as f:
                if existing_content and not existing_content.endswith("\n"):
                    f.write("\n")
                f.write("\n".join(lines_to_add) + "\n")
            print(f"Updated .gitignore with AI commit generator entries")
