"""Configuration for unit tests."""

from importlib import util
from pathlib import Path
from typing import Dict, Sequence

import pytest
from pytest import Config, Function, Parser

from zai.core.logs import (
	get_config_dict,
	get_log_file,
	get_timestamp_ms,
)


def pytest_addoption(parser: Parser) -> None:
	"""Add custom command line options to pytest."""
	parser.addoption(
		'--only-extended',
		action='store_true',
		help='Only run extended tests. Does not allow skipping any extended tests.',
	)
	parser.addoption(
		'--only-core',
		action='store_true',
		help='Only run core tests. Never runs any extended tests.',
	)


def pytest_collection_modifyitems(config: Config, items: Sequence[Function]) -> None:
	"""Add implementations for handling custom markers.

	At the moment, this adds support for a custom `requires` marker.

	The `requires` marker is used to denote tests that require one or more packages
	to be installed to run. If the package is not installed, the test is skipped.

	The `requires` marker syntax is:

	.. code-block:: python

	    @pytest.mark.requires('package1', 'package2')
	    def test_something(): ...
	"""
	# Mapping from the name of a package to whether it is installed or not.
	# Used to avoid repeated calls to `util.find_spec`
	required_pkgs_info: Dict[str, bool] = {}

	only_extended = config.getoption('--only-extended') or False
	only_core = config.getoption('--only-core') or False

	if only_extended and only_core:
		raise ValueError('Cannot specify both `--only-extended` and `--only-core`.')

	for item in items:
		requires_marker = item.get_closest_marker('requires')
		if requires_marker is not None:
			if only_core:
				item.add_marker(pytest.mark.skip(reason='Skipping not a core test.'))
				continue

			# Iterate through the list of required packages
			required_pkgs = requires_marker.args
			for pkg in required_pkgs:
				# If we haven't yet checked whether the pkg is installed
				# let's check it and store the result.
				if pkg not in required_pkgs_info:
					try:
						installed = util.find_spec(pkg) is not None
					except Exception:
						installed = False
					required_pkgs_info[pkg] = installed

				if not required_pkgs_info[pkg]:
					if only_extended:
						pytest.fail(
							f'Package `{pkg}` is not installed but is required for '
							f'extended tests. Please install the given package and '
							f'try again.',
						)

					else:
						# If the package is not installed, we immediately break
						# and mark the test as skipped.
						item.add_marker(pytest.mark.skip(reason=f'Requires pkg: `{pkg}`'))
						break
		else:
			if only_extended:
				item.add_marker(pytest.mark.skip(reason='Skipping not an extended test.'))


@pytest.fixture
def logging_conf() -> dict:
	return get_config_dict(
		'info',
		get_log_file(log_path='logs', sub_dir=f'local_{get_timestamp_ms()}'),
		1024 * 1024,
		1024 * 1024 * 1024,
	)


@pytest.fixture
def test_file_path(request) -> Path:
	from pathlib import Path

	# Current execution directory
	# Get the path of the current test file
	test_file_path = Path(str(request.fspath)).parent
	print('test_file_path:', test_file_path)
	return test_file_path
