"""Git operations — branch detection, diff summary, files changed."""

from __future__ import annotations

from pathlib import Path
from typing import Optional


def _repo(repo_root: Path):
    """Lazy import and return a git.Repo instance."""
    from git import Repo, InvalidGitRepositoryError

    try:
        return Repo(repo_root)
    except InvalidGitRepositoryError:
        return None


def get_current_branch(repo_root: Path) -> str:
    """Return current branch name, or short SHA if detached HEAD."""
    repo = _repo(repo_root)
    if repo is None:
        return "unknown"
    try:
        if repo.head.is_detached:
            return repo.head.commit.hexsha[:8]
        return repo.active_branch.name
    except (TypeError, ValueError):
        return "unknown"


def get_files_changed(repo_root: Path) -> list[str]:
    """Return list of files changed (staged + unstaged + untracked)."""
    repo = _repo(repo_root)
    if repo is None:
        return []
    files: set[str] = set()
    # Staged changes
    if repo.head.is_valid():
        for diff in repo.index.diff(repo.head.commit):
            if diff.a_path:
                files.add(diff.a_path)
            if diff.b_path:
                files.add(diff.b_path)
    # Unstaged changes
    for diff in repo.index.diff(None):
        if diff.a_path:
            files.add(diff.a_path)
        if diff.b_path:
            files.add(diff.b_path)
    # Untracked files
    files.update(repo.untracked_files)
    return sorted(files)


def get_diff_summary(repo_root: Path) -> str:
    """Return a short diff stat summary string."""
    repo = _repo(repo_root)
    if repo is None:
        return ""
    try:
        diff_stat = repo.git.diff("--stat")
        lines = diff_stat.strip().splitlines()
        return lines[-1].strip() if lines else ""
    except Exception:
        return ""


def get_full_diff(repo_root: Path) -> str:
    """Return the full diff output."""
    repo = _repo(repo_root)
    if repo is None:
        return ""
    try:
        return repo.git.diff()
    except Exception:
        return ""


def get_recent_commits(repo_root: Path, count: int = 5) -> list[str]:
    """Return recent commit messages (one-line each)."""
    repo = _repo(repo_root)
    if repo is None:
        return []
    try:
        commits = list(repo.iter_commits(max_count=count))
        return [f"{c.hexsha[:7]} {c.summary}" for c in commits]
    except Exception:
        return []


def get_hooks_dir(repo_root: Path) -> Path:
    """Return the git hooks directory."""
    repo = _repo(repo_root)
    if repo is not None:
        # Respect core.hooksPath if set
        try:
            hooks_path = repo.config_reader().get_value("core", "hooksPath")
            return Path(hooks_path)
        except Exception:
            pass
    return repo_root / ".git" / "hooks"
