from mpsd_software_manager.cmds import status


def test_environment_status(
    tmp_path, simple_toolchain, create_fake_environment, install_test_release
):
    """Test that the environment status is correct.

    The status command has the following three usage:

    - 1) If no mpsd_release, list available releases
    - 2) If mpsd_release, list available toolchains
    - 3) If mpsd_release and toolchain, list available packages

    We need to test all the three cases.
    """

    # 1) If no mpsd_release, list available releases
    list_of_release_in_empty_dir = status.environment_status(None, tmp_path)
    assert list_of_release_in_empty_dir == []
    (tmp_path / "test_case1" / "dev-23a" / "spack-environments").mkdir(
        parents=True, exist_ok=True
    )
    (tmp_path / "test_case1" / "fake_release").mkdir(parents=True, exist_ok=True)
    list_of_release = status.environment_status(None, tmp_path / "test_case1")
    assert list_of_release == ["dev-23a"]

    # 2) If mpsd_release, list available toolchains
    toolchain_map = status.environment_status("fake-release", tmp_path)
    assert toolchain_map is None
    mpsd_release = "dev-23a"
    expected_toolchain_map = create_fake_environment(tmp_path, mpsd_release)
    # check that the environment status is is correct
    toolchain_map = status.environment_status(mpsd_release, tmp_path)
    # convert each list to a set to ensure that the order doesn't matter
    for microarch in expected_toolchain_map:
        assert set(toolchain_map[microarch]) == set(expected_toolchain_map[microarch])

    # 3) If mpsd_release and toolchain, list available packages
    install_test_release(tmp_path / "test_case3", simple_toolchain)
    package_list = status.environment_status(
        mpsd_release, tmp_path / "test_case3", "toolchain2"
    )
    assert len(package_list) == 2  # we installed zlib and zstd only
    check_for_valid_spec_syntax(
        package_list[0], "zlib"
    )  # the list is always in alphabetical order
    check_for_valid_spec_syntax(package_list[1], "zstd")


def check_for_valid_spec_syntax(spec: str, package_name: str):
    """Check if the spec is valid.

    Assuming the format of the spec as:
    {name}{@versions}{%compiler.name}{@compiler.versions}{compiler_flags}{variants}{arch=architecture}
    we ensure that:
    - package name is correct
    - there are atleast 2 @ symbols (version for package and compiler)
    - there is atleast 1 % symbol  (compiler specification)
    - there is atleast 1 arch=
    """
    assert spec.count("@") >= 2
    assert spec.count("%") >= 1
    assert "build_system=" in spec
    assert "arch=" in spec
    assert spec.split("@")[0] == package_name