"""JavaScript module tests. Skipped unless pytest is run with --js-tests."""

from __future__ import annotations

import importlib.util
import sys
from collections.abc import Iterator
from pathlib import Path
from types import ModuleType
from typing import Any, cast

import pytest
from pygitweb.static_tests.js_runtime import JsPage, available_engines


class _FileModule(pytest.Module):
	def _getobj(self) -> ModuleType:
		name = "js_tests_" + self.path.stem.replace("-", "_")
		spec = importlib.util.spec_from_file_location(name, self.path)
		if spec is None or spec.loader is None:
			raise ImportError(f"cannot load {self.path}")
		module = importlib.util.module_from_spec(spec)
		sys.modules[name] = module
		spec.loader.exec_module(module)
		return module


@pytest.hookimpl(hookwrapper=True)
def pytest_collect_file(file_path: Path, parent: pytest.Collector) -> object:
	outcome = yield
	if file_path.suffix != ".py" or not file_path.name.startswith("test_") or "-" not in file_path.name:
		return
	# pytest 9 gathers every pytest_collect_file result, so the default collector
	# would import this hyphenated module a second time.
	cast(Any, outcome).force_result([_FileModule.from_parent(parent, path=file_path)])


def pytest_generate_tests(metafunc: pytest.Metafunc) -> None:
	if "js" not in metafunc.fixturenames:
		return
	engines = available_engines()
	if engines:
		metafunc.parametrize("js", engines, indirect=True, ids=engines)
	else:
		metafunc.parametrize("js", ["none"], indirect=True)


@pytest.fixture
def js(request: pytest.FixtureRequest) -> Iterator[JsPage]:
	if request.param == "none":
		pytest.skip("No JS engine installed. uv sync --group pythonmonkey  or  uv sync --group stpyv8")
	page = JsPage(str(request.param))
	yield page
	page.close()