from __future__ import annotations

import subprocess
from typing import Optional


def _run_git(args: list[str], cwd: Optional[str] = None) -> subprocess.CompletedProcess:
    return subprocess.run(
        ["git", *args],
        cwd=cwd,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        check=False,
    )


def is_git_repo(cwd: Optional[str] = None) -> bool:
    result = _run_git(["rev-parse", "--is-inside-work-tree"], cwd=cwd)
    return result.returncode == 0


def get_staged_paths(cwd: Optional[str] = None) -> list[str]:
    result = _run_git(["diff", "--cached", "--name-only", "--diff-filter=ACMR"], cwd=cwd)
    if result.returncode != 0:
        return []
    output = result.stdout.decode("utf-8", errors="replace")
    return [line.strip() for line in output.splitlines() if line.strip()]


def get_staged_blob(path: str, cwd: Optional[str] = None) -> Optional[bytes]:
    result = _run_git(["show", f":{path}"], cwd=cwd)
    if result.returncode != 0:
        return None
    return result.stdout


def get_staged_numstat(path: str, cwd: Optional[str] = None) -> Optional[tuple[str, str]]:
    result = _run_git(["diff", "--cached", "--numstat", "--", path], cwd=cwd)
    if result.returncode != 0:
        return None
    output = result.stdout.decode("utf-8", errors="replace").strip()
    if not output:
        return None
    parts = output.split("\t")
    if len(parts) < 3:
        return None
    return parts[0], parts[1]


def is_binary_blob(blob: bytes) -> bool:
    return b"\x00" in blob


def is_binary_path(path: str, cwd: Optional[str] = None) -> bool:
    numstat = get_staged_numstat(path, cwd=cwd)
    if numstat is None:
        return False
    added, deleted = numstat
    return added == "-" and deleted == "-"
