"""Exercise maintenance delivery against an actual protected bare Git remote."""
import json
import os
from pathlib import Path
import subprocess
import tempfile
import unittest


SCRIPT = Path(os.environ.get("MAINTENANCE_SCRIPT", Path(__file__).with_name("commit_bot_changes.sh")))


class MaintenanceFixture(unittest.TestCase):
    def setUp(self):
        self.temp = tempfile.TemporaryDirectory(prefix="source-maintenance-")
        self.addCleanup(self.temp.cleanup)
        self.root = Path(self.temp.name)
        self.repo, self.remote = self.root / "repo", self.root / "remote.git"
        self.repo.mkdir()
        self.env = {**os.environ, "GITHUB_REPOSITORY": "example/app", "GITHUB_RUN_ID": "1234",
                    "GITHUB_REF_NAME": "main", "GIT_TERMINAL_PROMPT": "0"}
        self.git("init", "--bare", str(self.remote))
        self.git("init", "-b", "main")
        self.git("config", "user.name", "Fixture")
        self.git("config", "user.email", "fixture@example.test")
        (self.repo / "project.yml").write_text("version: 1.0\n")
        (self.repo / "unrelated.txt").write_text("original\n")
        self.git("add", ".")
        self.git("commit", "-m", "Initial fixture")
        self.git("remote", "add", "origin", "https://github.com/example/app.git")
        self.git("config", f"url.{self.remote}.insteadOf", "https://github.com/example/app.git")
        self.git("push", "-u", "origin", "main")
        self.base = self.git("rev-parse", "HEAD").strip()
        self.env["GITHUB_SHA"] = self.base
        self.hook = self.remote / "hooks/pre-receive"
        self.hook.write_text("#!/bin/sh\nwhile read old new ref; do\n"
                             "  [ \"$ref\" != refs/heads/main ] || exit 1\ndone\n")
        self.hook.chmod(0o755)

    def git(self, *args):
        return subprocess.check_output(["git", *args], cwd=self.repo, env=self.env,
                                       stderr=subprocess.DEVNULL, text=True)

    def stage(self):
        (self.repo / "project.yml").write_text("version: 1.1\n")
        self.git("add", "project.yml")
        (self.repo / "unrelated.txt").write_text("unfinished build change\n")

    def run_script(self):
        return subprocess.run(["bash", str(getattr(self, "script", SCRIPT))], cwd=self.repo, env=self.env,
                              text=True, capture_output=True, timeout=15)

    def receipt(self, result):
        self.assertEqual(result.returncode, 0, result.stderr)
        lines = [line for line in result.stdout.splitlines()
                 if line.startswith("::notice title=source_maintenance_pending::")]
        self.assertEqual(len(lines), 1, result.stdout + result.stderr)
        return json.loads(lines[0].split("::", 2)[2])
