"""Setup's first push when the remote branch moved on (for example, a codegen run committed the workflow
to the default branch). Runs real git against a local bare repository. No network."""

import subprocess
import tempfile
from pathlib import Path

import pytest

from src.workers.repo_ops import ensure_git_remote_push


def _git(cwd, *args):
    return subprocess.run(["git", *args], cwd=cwd, capture_output=True, text=True, check=True).stdout.strip()


def _commit(cwd, name, text, message):
    (Path(cwd) / name).write_text(text, encoding="utf-8")
    _git(cwd, "add", name)
    _git(cwd, "-c", "user.name=t", "-c", "user.email=t@t", "commit", "-q", "-m", message)


def _setup(tmp):
    root = Path(tmp)
    remote = root / "remote.git"
    local = root / "local"
    other = root / "other"
    _git(root, "init", "-q", "--bare", "-b", "main", str(remote))
    _git(root, "init", "-q", "-b", "main", str(local))
    _commit(local, "app.txt", "app\n", "feat: initial boilerplate")
    return remote, local, other


def _clone_and_commit(remote, other, name, text, message):
    subprocess.run(["git", "clone", "-q", str(remote), str(other)], check=True, capture_output=True)
    _commit(other, name, text, message)
    _git(other, "push", "-q", "origin", "main")


@pytest.mark.asyncio
async def test_push_rebases_onto_a_remote_commit_made_after_our_first_commit():
    with tempfile.TemporaryDirectory() as tmp:
        remote, local, other = _setup(tmp)
        _clone_and_commit(remote, other, ".github-codegen.yml", "workflow\n", "[p2hs] ensure codegen workflow")

        await ensure_git_remote_push(str(local), str(remote), "main")

        remote_log = _git(remote, "log", "--format=%s", "main")
        assert "feat: initial boilerplate" in remote_log
        assert "[p2hs] ensure codegen workflow" in remote_log
        assert _git(remote, "show", "main:.github-codegen.yml") == "workflow"


@pytest.mark.asyncio
async def test_a_conflicting_remote_commit_fails_the_push_and_leaves_the_remote_alone():
    with tempfile.TemporaryDirectory() as tmp:
        remote, local, other = _setup(tmp)
        _clone_and_commit(remote, other, "app.txt", "remote version\n", "remote change")
        before = _git(remote, "rev-parse", "main")

        with pytest.raises(RuntimeError, match="rebase onto remote failed"):
            await ensure_git_remote_push(str(local), str(remote), "main")

        assert _git(remote, "rev-parse", "main") == before
        assert _git(local, "status", "--porcelain") == ""
