#!/usr/bin/env python3


import os
import subprocess
import sys
import textwrap
import time
from pathlib import Path

import click


def shell(cmd: str, *, check: bool, **kwargs: object) -> subprocess.CompletedProcess[str]:
    return subprocess.run([cmd], shell=True, check=check, **kwargs)  # type: ignore[call-overload, no-any-return]


def git_repo_has_changes() -> bool:
    unstaged_changes: bool = shell("git diff-index --quiet HEAD --", check=False).returncode != 0
    staged_changes: bool = (
        shell("git diff-index --quiet --cached HEAD --", check=False).returncode != 0
    )
    return unstaged_changes or staged_changes


@click.command()
def main() -> None:
    project_root = Path(__file__).parent / ".."
    os.chdir(project_root)

    if git_repo_has_changes():
        print("Your git repo has uncommitted changes. Commit or stash before continuing.")
        sys.exit(1)

    previous_branch = shell(
        "git rev-parse --abbrev-ref HEAD", check=True, capture_output=True, encoding="utf8"
    ).stdout.strip()

    shell("git fetch origin", check=True)

    timestamp = time.strftime("%Y-%m-%dT%H-%M-%S", time.gmtime())
    branch_name = f"update-constraints-{timestamp}"

    shell(f"git checkout -b {branch_name} origin/main", check=True)

    try:
        shell("bin/update_dependencies.py", check=True)

        if not git_repo_has_changes():
            print("Done: no constraint updates required.")
            return

        shell('git commit -a -m "Update dependencies"', check=True)
        body = textwrap.dedent(
            f"""
            Update the versions of our dependencies.

            PR generated by `{Path(__file__).name}`.
            """
        )
        subprocess.run(
            [
                "gh",
                "pr",
                "create",
                "--repo=pypa/cibuildwheel",
                "--base=main",
                "--title=Update dependencies",
                f"--body='{body}'",
            ],
            check=True,
        )

        print("Done.")
    finally:
        # remove any local changes
        shell("git checkout -- .", check=True)
        shell(f"git checkout {previous_branch}", check=True)
        shell(f"git branch -D --force {branch_name}", check=True)


if __name__ == "__main__":
    main.main(standalone_mode=True)
