#!/usr/bin/env python3
# WL-Pre-Push-Hook-Version: consolidated-python-branch-protection
"""
Pre-push hook: prevents direct pushes to main and develop branches.

Replaces the previous Bash/Bat multi-file implementation with a single
cross-platform Python script. Designed to be copied by hooks_manager.py
as the active .wl/hooks/pre-push.

Behavior:
  - Parses stdin for git pre-push input (one line per ref being pushed).
  - Blocks pushes where the remote ref is refs/heads/main or refs/heads/develop.
  - Blocks --no-verify / -n flags (prevents bypass attempts).
  - All other refs (feature branches, tags, deletions) are allowed.
  - On parse failure, prints a warning and exits 0 (fail-open).
"""

import os
import sys

# Set stdout/stderr encoding to UTF-8 for cross-platform emoji support.
# On Windows with Chinese locale (GBK), emoji characters crash print().
if sys.stdout.encoding and sys.stdout.encoding.upper() not in ("UTF-8", "UTF8"):
    _stdout = sys.stdout.buffer if hasattr(sys.stdout, "buffer") else None
    if _stdout:
        sys.stdout = type(sys.stdout)(
            _stdout,
            encoding="utf-8",
            errors="replace",
        )
    _stderr = sys.stderr.buffer if hasattr(sys.stderr, "buffer") else None
    if _stderr:
        sys.stderr = type(sys.stderr)(
            _stderr,
            encoding="utf-8",
            errors="replace",
        )


def check_no_verify(argv: list[str]) -> int | None:
    """Return exit code 1 if --no-verify or -n is present, None otherwise."""
    if "--no-verify" in argv or "-n" in argv:
        print(
            "错误: 不允许使用 --no-verify 或 -n 选项绕过 pre-push 检查。",
            file=sys.stderr,
        )
        print(
            "请使用 feature 分支推送代码，而不是绕过分支保护。",
            file=sys.stderr,
        )
        print(file=sys.stderr)
        print(
            "ERROR: --no-verify/-n is not allowed for protected branches.",
            file=sys.stderr,
        )
        print(
            "Use a feature branch instead of bypassing branch protection.",
            file=sys.stderr,
        )
        return 1
    return None


def read_stdin() -> str:
    """Read all stdin input, handling bytes decoding."""
    try:
        raw = sys.stdin.buffer.read()
        return raw.decode("utf-8", errors="replace")
    except AttributeError:
        # Fallback when sys.stdin.buffer is unavailable
        return sys.stdin.read()


def parse_remote_refs(data: str) -> list[str]:
    """
    Parse git pre-push stdin and extract remote ref names.

    Git pre-push format (one line per ref being pushed):
        <local-ref> <local-sha1> <remote-ref> <remote-sha1>

    Returns list of remote refs like 'refs/heads/main'.
    """
    refs: list[str] = []
    for line in data.splitlines():
        line = line.strip()
        if not line:
            continue

        parts = line.split()
        # Format: local-ref local-sha remote-ref remote-sha
        if len(parts) >= 4:
            remote_ref = parts[2]
            if remote_ref.startswith("refs/heads/"):
                refs.append(remote_ref)
            # Tags (refs/tags/) and other refs are not checked
    return refs


def check_branch_protection(remote_refs: list[str]) -> int:
    """Check if any remote ref is a protected branch. Returns 1 if blocked."""
    protected_branches = {"refs/heads/main", "refs/heads/develop"}

    for ref in remote_refs:
        if ref in protected_branches:
            branch = ref.removeprefix("refs/heads/")
            print(f'🚫 PUSH BLOCKED: Direct push to "{branch}" branch is not allowed.')
            print()
            print("📋 Git Flow Policy:")
            print("   - Never push directly to main or develop")
            print("   - Create a feature/fix branch for your changes")
            print("   - Submit changes via Pull Request only")
            print()
            print("🤖 For AI Agents:")
            print("   - Use `git checkout -b feature/<description>` to create a branch")
            print(
                "   - Push to your feature branch instead:"
                " `git push origin feature/<description>`"
            )
            print("   - Then create a Pull Request for review")
            return 1

    return 0


def main() -> int:
    """Main entry point for the pre-push hook."""

    # Step 1: Block --no-verify bypass attempts
    result = check_no_verify(sys.argv)
    if result is not None:
        return result

    # Step 2: Read stdin
    try:
        data = read_stdin()
    except Exception as exc:
        print(
            f"Warning: Could not read pre-push input: {exc}",
            file=sys.stderr,
        )
        print(
            "Warning: Branch protection check skipped.",
            file=sys.stderr,
        )
        return 0  # fail-open

    # Step 3: Parse remote refs from stdin
    remote_refs = parse_remote_refs(data)

    # Step 4: Check branch protection
    return check_branch_protection(remote_refs)


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