#!/usr/bin/env python3
"""
Submodule-First Commit Guard — Ensures submodules are committed before parent.

Parses .gitmodules to discover submodule paths, then checks each for
uncommitted changes. If any submodule has dirty tracked files, the commit
is blocked so the submodule can be committed first.

Usage:
    check_submodule_order.py    # Run from any project with submodules

Exit codes:
    0 — No submodules, or all submodules are clean
    2 — Blocked: one or more submodules have uncommitted changes
"""
import configparser
import subprocess
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]


def parse_submodule_paths() -> list[str]:
    """Read .gitmodules and return list of submodule paths."""
    gitmodules = ROOT / ".gitmodules"
    if not gitmodules.is_file():
        return []

    config = configparser.ConfigParser()
    config.read(str(gitmodules))

    paths: list[str] = []
    for section in config.sections():
        if section.startswith("submodule "):
            path = config.get(section, "path", fallback=None)
            if path:
                paths.append(path)
    return paths


def get_dirty_files(submodule_path: str) -> list[str]:
    """Return list of dirty tracked files in a submodule (ignoring untracked)."""
    abs_path = ROOT / submodule_path
    if not abs_path.is_dir():
        return []

    result = subprocess.run(
        ["git", "status", "--porcelain"],
        capture_output=True,
        text=True,
        cwd=abs_path,
    )
    dirty: list[str] = []
    for line in result.stdout.strip().splitlines():
        line = line.strip()
        if not line:
            continue
        # Skip untracked files (lines starting with ??)
        if line.startswith("??"):
            continue
        dirty.append(line)
    return dirty


def main() -> int:
    paths = parse_submodule_paths()
    if not paths:
        return 0

    blocked: list[tuple[str, int]] = []

    for sub_path in paths:
        dirty = get_dirty_files(sub_path)
        if dirty:
            blocked.append((sub_path, len(dirty)))

    if not blocked:
        return 0

    print("SUBMODULE-FIRST COMMIT GUARD — BLOCKED", file=sys.stderr)
    print(file=sys.stderr)
    for sub_path, count in blocked:
        print(
            f"  {sub_path}: {count} dirty file(s) — commit submodule first",
            file=sys.stderr,
        )
    print(file=sys.stderr)
    print(
        "Commit each dirty submodule before committing the parent repo.",
        file=sys.stderr,
    )
    return 2


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