"""Test fixtures."""
import copy
import logging
import subprocess

import pytest
import yaml

import mpsd_software_manager

# set loglevel to debug - useful for understanding problems.
# (if the tests pass, pytest doesn't show any output)
import mpsd_software_manager.utils.logging
from mpsd_software_manager.utils.filesystem_utils import os_chdir

mpsd_software_manager.utils.logging.set_up_logging(
    loglevel="debug", file_path="tests.log"
)
logging.debug(f"We have set up logging from {__file__}")


@pytest.fixture
def create_mock_git_repository():
    """
    Create a git repository in the directory `target_directory`.

    Arguments
    ---------
    target_directory : pathlib.Path
      - path at which the root of the repository should be located (i.e. `.git` folder)

    create_directory : bool
      - create `target_directory` and parent directories if True

    """

    def _create_mock_git_repository(target_directory, create_directory=True):
        # create directory first
        if create_directory:
            target_directory.mkdir(parents=True)

        # then create git repository:
        with os_chdir(str(target_directory)):
            subprocess.run("git init .", shell=True, check=True)
            subprocess.run("echo 'fake content' > readme.txt", shell=True, check=True)
            subprocess.run("git add readme.txt", shell=True, check=True)
            subprocess.run("pwd", shell=True)

            # if email and username are not available (such as on naked test container),
            # git may complain. We set a temporary user for this one commit to work
            # around that.
            user_details = "-c user.name='Tes Ta' -c user.email='tester@some-ci.org'"
            subprocess.run(
                f'git {user_details} commit -m "first commit" readme.txt',
                shell=True,
                check=True,
            )

    return _create_mock_git_repository


@pytest.fixture
def simple_toolchain():
    """Return a dict for a simple toolchain."""
    dict = {
        "spack": {
            "specs": ["zlib@1.2.13"],
            "view": True,
            "concretizer": {"reuse": False, "unify": True},
        }
    }
    return dict


@pytest.fixture
def create_fake_environment():
    """Create a fake environment with toolchains for testing."""

    def _create_fake_environment(tmp_path, mpsd_release, expected_toolchain_map=None):
        if not expected_toolchain_map:
            test_microarch = (
                mpsd_software_manager.utils.microarch.get_native_microarchitecture()
            )
            expected_toolchain_map = {test_microarch: ["foss2021a", "intel2021a"]}

            spe_folder = tmp_path / mpsd_release / "spack-environments"
            spe_folder.mkdir(parents=True, exist_ok=True)
        for microarch in expected_toolchain_map:
            toolchain_lmod_folder = (
                tmp_path / mpsd_release / microarch / "lmod" / "Core" / "toolchains"
            )
            toolchain_lmod_folder.mkdir(parents=True, exist_ok=True)
            spack_folder = tmp_path / mpsd_release / microarch / "spack"
            spack_folder.mkdir(parents=True, exist_ok=True)
            logs_folder = tmp_path / mpsd_release / "logs"
            logs_folder.mkdir(parents=True, exist_ok=True)
            # Simulate the creation of APEX.log
            # (which is created by the main function)
            (logs_folder / "APEX.log").touch()
            for toolchain in expected_toolchain_map[microarch]:
                toolchain_lua_file = toolchain_lmod_folder / f"{toolchain}.lua"
                toolchain_lua_file.touch()

        return expected_toolchain_map

    return _create_fake_environment


@pytest.fixture
def install_test_release(tmp_path, simple_toolchain):
    """Install a test release.

    with toolchain1 and toolchain2 to use for testing.
    """

    def _install_test_release(tmp_path, simple_toolchain):
        release_to_test = "dev-23a"
        # prepare a release directory
        mpsd_software_manager.cmds.prepare.prepare_environment(
            mpsd_release=release_to_test, root_dir=tmp_path
        )

        microarch = mpsd_software_manager.utils.microarch.get_native_microarchitecture()
        tmp_path / release_to_test / microarch
        spe_dir = tmp_path / release_to_test / "spack-environments"

        # create sample toolchains
        simple_toolchain_string = yaml.dump(simple_toolchain)
        simple_toolchain_2 = copy.deepcopy(simple_toolchain)
        simple_toolchain_2["spack"]["specs"] = ["zlib@1.2.13", "zstd@1.5.2"]
        simple_toolchain2_string = yaml.dump(simple_toolchain_2)
        toolchain1_dir = spe_dir / "toolchains" / "toolchain1"
        toolchain2_dir = spe_dir / "toolchains" / "toolchain2"
        toolchain1_dir.mkdir(parents=True)
        toolchain2_dir.mkdir(parents=True)
        (toolchain1_dir / "spack.yaml").write_text(simple_toolchain_string)
        (toolchain2_dir / "spack.yaml").write_text(simple_toolchain2_string)

        # install the release
        mpsd_software_manager.cmds.install.install_environment(
            mpsd_release=release_to_test,
            package_sets=["toolchain1", "toolchain2"],
            root_dir=tmp_path,
        )

    return _install_test_release