#!/usr/bin/env python3
import json
import re
import subprocess
import sys
from pathlib import Path

REPO_ROOT = Path(subprocess.check_output(["git", "rev-parse", "--show-toplevel"], text=True).strip())
PLUGIN_JSON_PATH = REPO_ROOT / "plugin.json"

STOP_PATTERNS = [
    r"\[no[-_ ]?bump\]",
    r"\[skip[-_ ]?bump\]",
    r"\[no[-_ ]?version[-_ ]?bump\]",
    r"\[skip[-_ ]?version\]",
    r"\bno[-_ ]bump\b",
    r"\bskip[-_ ]bump\b",
    r"\bno[-_ ]version[-_ ]bump\b",
]


def increment_patch_version(version_str: str) -> str:
    match = re.fullmatch(r"^(\d+)\.(\d+)\.(\d+)(.*)$", version_str.strip())
    if not match:
        raise ValueError(f"Version '{version_str}' does not match x.y.z format")
    major, minor, patch, suffix = match.groups()
    new_patch = int(patch) + 1
    return f"{major}.{minor}.{new_patch}{suffix}"


def get_head_version() -> str | None:
    res = subprocess.run(
        ["git", "rev-parse", "--verify", "HEAD"],
        cwd=REPO_ROOT,
        stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL,
    )
    if res.returncode != 0:
        return None

    show_res = subprocess.run(
        ["git", "show", "HEAD:plugin.json"],
        cwd=REPO_ROOT,
        stdout=subprocess.PIPE,
        stderr=subprocess.DEVNULL,
        text=True,
    )
    if show_res.returncode != 0:
        return None

    try:
        head_data = json.loads(show_res.stdout)
        return str(head_data.get("version")) if "version" in head_data else None
    except json.JSONDecodeError:
        return None


def should_skip_from_commit_msg() -> bool:
    # 1. Check GIT_PARAMS / COMMIT_EDITMSG / MERGE_MSG
    candidates = [
        REPO_ROOT / ".git" / "COMMIT_EDITMSG",
        REPO_ROOT / ".git" / "MERGE_MSG",
    ]
    for p in candidates:
        if p.exists():
            content = p.read_text(encoding="utf-8", errors="replace")
            lines = [line for line in content.splitlines() if not line.strip().startswith("#")]
            text = " ".join(lines)
            for pattern in STOP_PATTERNS:
                if re.search(pattern, text, re.IGNORECASE):
                    return True

    # 2. Check process command-line arguments (e.g. git commit -m "...")
    try:
        # On Linux, inspect parent process /proc cmdline
        ppid = subprocess.check_output(["ps", "-o", "ppid=", "-p", str(Path("/proc/self").resolve().name)], text=True).strip()
        cmdline_path = Path(f"/proc/{ppid}/cmdline")
        if cmdline_path.exists():
            cmd_args = cmdline_path.read_bytes().decode("utf-8", errors="replace")
            for pattern in STOP_PATTERNS:
                if re.search(pattern, cmd_args, re.IGNORECASE):
                    return True
    except Exception:
        pass

    return False


def main() -> int:
    # Don't auto-bump during merge/rebase in progress
    if (REPO_ROOT / ".git" / "MERGE_HEAD").exists() or (REPO_ROOT / ".git" / "rebase-merge").exists():
        return 0

    if should_skip_from_commit_msg():
        print("pre-commit: stop word detected in commit message, skipping version bump")
        return 0

    if not PLUGIN_JSON_PATH.exists():
        return 0

    try:
        data = json.loads(PLUGIN_JSON_PATH.read_text(encoding="utf-8"))
        current_version = str(data.get("version", ""))
    except Exception as e:
        print(f"pre-commit: failed to parse {PLUGIN_JSON_PATH}: {e}", file=sys.stderr)
        return 1

    head_version = get_head_version()

    # Skip if version was manually changed (differs from HEAD)
    if head_version is not None and current_version != head_version:
        print(
            f"pre-commit: version already modified ({head_version} -> {current_version}), skipping auto-increment"
        )
        return 0

    try:
        new_version = increment_patch_version(current_version)
        data["version"] = new_version
        PLUGIN_JSON_PATH.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
    except Exception as e:
        print(f"pre-commit: failed to bump version in {PLUGIN_JSON_PATH}: {e}", file=sys.stderr)
        return 1

    res = subprocess.run(["git", "add", str(PLUGIN_JSON_PATH)], cwd=REPO_ROOT)
    if res.returncode != 0:
        print("pre-commit: failed to stage plugin.json", file=sys.stderr)
        return res.returncode

    print(f"pre-commit: bumped version {current_version} -> {new_version}")
    return 0


if __name__ == "__main__":
    sys.exit(main())
