"""Git helpers with fallback when git is absent."""

from __future__ import annotations

import subprocess
import pathlib


def git_available(repo_root: pathlib.Path) -> bool:
    try:
        result = subprocess.run(
            ["git", "rev-parse", "--is-inside-work-tree"],
            cwd=str(repo_root),
            capture_output=True,
            text=True,
            timeout=5,
        )
        return result.returncode == 0
    except (FileNotFoundError, subprocess.TimeoutExpired):
        return False


def is_repo_dirty(repo_root: pathlib.Path) -> bool | None:
    """Return True if dirty, False if clean, None if git not available."""
    if not git_available(repo_root):
        return None
    result = subprocess.run(
        ["git", "status", "--porcelain"],
        cwd=str(repo_root),
        capture_output=True,
        text=True,
        timeout=10,
    )
    return bool(result.stdout.strip())


def git_diff(repo_root: pathlib.Path) -> str | None:
    """Return git diff output or None if git not available."""
    if not git_available(repo_root):
        return None
    result = subprocess.run(
        ["git", "diff"],
        cwd=str(repo_root),
        capture_output=True,
        text=True,
        timeout=10,
    )
    return result.stdout


def git_branch(repo_root: pathlib.Path) -> str | None:
    """Return current branch name, or None if git not available / detached."""
    if not git_available(repo_root):
        return None
    result = subprocess.run(
        ["git", "rev-parse", "--abbrev-ref", "HEAD"],
        cwd=str(repo_root),
        capture_output=True,
        text=True,
        timeout=5,
    )
    if result.returncode != 0:
        return None
    branch = result.stdout.strip()
    return None if branch == "HEAD" else branch


def git_commit(repo_root: pathlib.Path) -> str | None:
    """Return current commit SHA, or None if git not available."""
    if not git_available(repo_root):
        return None
    result = subprocess.run(
        ["git", "rev-parse", "HEAD"],
        cwd=str(repo_root),
        capture_output=True,
        text=True,
        timeout=5,
    )
    if result.returncode != 0:
        return None
    return result.stdout.strip() or None


def get_repo_info(repo_root: pathlib.Path) -> dict:
    """Collect repo state snapshot for manifest."""
    avail = git_available(repo_root)
    return {
        "git_available": avail,
        "branch": git_branch(repo_root) if avail else None,
        "commit": git_commit(repo_root) if avail else None,
        "is_dirty_before": is_repo_dirty(repo_root),
        "is_dirty_after": None,
    }
