"""Exercise the submission gate in disposable Git repositories."""

import os
from pathlib import Path
import shutil
import subprocess
import tempfile
import unittest


SCRIPT = Path(os.environ.get(
    "ZHCT_PRE_SUBMIT_SCRIPT", Path(__file__).resolve().parents[1] / "pre_submit_check.sh"
))


class PreSubmitCheckTests(unittest.TestCase):
    def run_gate(self, content, *, tracked=False, fallback=False, staged=False):
        with tempfile.TemporaryDirectory() as directory:
            root = Path(directory)
            subprocess.run(["git", "init", "-q", str(root)], check=True)
            file = root / "fixture.txt"
            file.write_text(content)
            if tracked or staged:
                subprocess.run(["git", "add", "fixture.txt"], cwd=root, check=True)
            env = os.environ.copy()
            if fallback:
                # Keep the gate's dependencies available while excluding ripgrep.
                binary_dir = root / "bin"
                binary_dir.mkdir()
                for command in ("git", "awk", "grep"):
                    (binary_dir / command).symlink_to(shutil.which(command))
                env["PATH"] = str(binary_dir)
            return subprocess.run(
                ["/bin/bash", str(SCRIPT)], cwd=root, env=env,
                text=True, capture_output=True, check=False,
            )

    def test_clean_text_and_log_separators_pass(self):
        for fallback in (False, True):
            with self.subTest(fallback=fallback):
                result = self.run_gate("ordinary text\n====================\n", fallback=fallback)
                self.assertEqual(result.returncode, 0, result.stdout + result.stderr)

    def test_each_conflict_marker_fails(self):
        for marker in ("<<<<<<< HEAD", "=======", ">>>>>>> origin/master"):
            for fallback in (False, True):
                for tracked in (False, True):
                    with self.subTest(marker=marker, fallback=fallback, tracked=tracked):
                        result = self.run_gate(marker + "\n", fallback=fallback, tracked=tracked)
                        self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)
                        self.assertIn("pre-submit check failed", result.stdout)

    def test_staged_whitespace_fails(self):
        result = self.run_gate("trailing whitespace   \n", staged=True)
        self.assertNotEqual(result.returncode, 0, result.stdout + result.stderr)
        self.assertIn("trailing whitespace", result.stdout)


if __name__ == "__main__":
    unittest.main()
