import importlib.util
import tempfile
import unittest
from pathlib import Path


def load_tdd_guard():
    module_path = Path(__file__).resolve().parent.parent / ".codex" / "hooks" / "tdd-guard.py"
    spec = importlib.util.spec_from_file_location("tdd_guard", module_path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module


class CppTddGuardTests(unittest.TestCase):
    def test_cpp_production_file_without_related_test_is_blocked(self):
        tdd_guard = load_tdd_guard()
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp)
            source = root / "include" / "fesa" / "Core" / "DofManager.hpp"
            source.parent.mkdir(parents=True)
            source.write_text("#pragma once\n", encoding="utf-8")

            self.assertEqual(tdd_guard._guarded_paths([str(source)], root, root), ["DofManager"])

    def test_cpp_production_file_with_module_test_is_allowed(self):
        tdd_guard = load_tdd_guard()
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp)
            source = root / "include" / "fesa" / "Core" / "DofManager.hpp"
            source.parent.mkdir(parents=True)
            source.write_text("#pragma once\n", encoding="utf-8")
            tests_dir = root / "tests"
            tests_dir.mkdir()
            (tests_dir / "test_core_module_includes.cpp").write_text("int main() { return 0; }\n", encoding="utf-8")

            self.assertEqual(tdd_guard._guarded_paths([str(source)], root, root), [])

    def test_cpp_production_file_with_basename_test_in_same_patch_is_allowed(self):
        tdd_guard = load_tdd_guard()
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp)
            source = root / "src" / "Math" / "DenseMatrix.cpp"
            source.parent.mkdir(parents=True)
            source.write_text("void f() {}\n", encoding="utf-8")
            test_path = root / "tests" / "test_dense_matrix.cpp"

            self.assertEqual(tdd_guard._guarded_paths([str(source), str(test_path)], root, root), [])

    def test_fortran_subroutine_without_related_test_is_blocked(self):
        tdd_guard = load_tdd_guard()
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp)
            source = root / "src" / "fortran" / "abaqus" / "UMAT.for"
            source.parent.mkdir(parents=True)
            source.write_text("      subroutine umat()\n      end\n", encoding="utf-8")

            self.assertEqual(tdd_guard._guarded_paths([str(source)], root, root), ["UMAT"])

    def test_fortran_subroutine_with_related_driver_test_is_allowed(self):
        tdd_guard = load_tdd_guard()
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp)
            source = root / "src" / "fortran" / "abaqus" / "UMAT.for"
            source.parent.mkdir(parents=True)
            source.write_text("      subroutine umat()\n      end\n", encoding="utf-8")
            test_path = root / "tests" / "fortran" / "test_umat_linear_elastic.f90"

            self.assertEqual(tdd_guard._guarded_paths([str(source), str(test_path)], root, root), [])

    def test_reference_artifacts_are_exempt(self):
        tdd_guard = load_tdd_guard()
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp)
            self.assertEqual(
                tdd_guard._guarded_paths(
                    [
                        "references/umat/single-element/model.inp",
                        "references/umat/single-element/stresses.csv",
                        "references/umat/single-element/job.msg.tail.txt",
                        "references/umat/single-element/job.dat.tail.txt",
                        "references/umat/single-element/job.log.tail.txt",
                    ],
                    root,
                    root,
                ),
                [],
            )

    def test_cmake_and_docs_are_exempt(self):
        tdd_guard = load_tdd_guard()
        with tempfile.TemporaryDirectory() as tmp:
            root = Path(tmp)
            self.assertEqual(
                tdd_guard._guarded_paths(["CMakeLists.txt", "docs/ARCHITECTURE.md", "cmake/toolchain.cmake"], root, root),
                [],
            )


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