import os
import textwrap

import pytest

from debputy.highlevel_manifest_parser import YAMLManifestParser, ManifestParseException


@pytest.fixture()
def manifest_parser_pkg_foo(
    amd64_dpkg_architecture_variables,
    dpkg_arch_query,
    package_single_foo_arch_all_cxt_amd64,
    null_substitution,
    no_profiles_or_build_options,
    debputy_plugin_feature_set,
) -> YAMLManifestParser:
    # We just need an empty directory really.  The "data" dir is "empty enough" to avoid picking up
    # any packager provided files
    debian_dir = os.path.join(os.path.dirname(__file__), "data")
    return YAMLManifestParser(
        "debian/test-debputy.manifest",
        package_single_foo_arch_all_cxt_amd64,
        null_substitution,
        amd64_dpkg_architecture_variables,
        dpkg_arch_query,
        no_profiles_or_build_options,
        debputy_plugin_feature_set,
        debian_dir=debian_dir,
    )


def test_parsing_no_manifest(manifest_parser_pkg_foo):
    manifest = manifest_parser_pkg_foo.build_manifest()

    assert [p.name for p in manifest.all_packages] == ["foo"]
    assert [p.name for p in manifest.active_packages] == ["foo"]


def test_parsing_version_only(manifest_parser_pkg_foo):
    content = textwrap.dedent(
        """\
    manifest-version: '0.1'
    """
    )

    manifest = manifest_parser_pkg_foo.parse_manifest(fd=content)

    assert [p.name for p in manifest.all_packages] == ["foo"]
    assert [p.name for p in manifest.active_packages] == ["foo"]


def test_parsing_package_foo_empty(manifest_parser_pkg_foo):
    content = textwrap.dedent(
        """\
    manifest-version: '0.1'
    packages:
        foo:
    """
    )

    manifest = manifest_parser_pkg_foo.parse_manifest(fd=content)

    assert [p.name for p in manifest.all_packages] == ["foo"]
    assert [p.name for p in manifest.active_packages] == ["foo"]


def test_parsing_package_bar_empty(manifest_parser_pkg_foo):
    content = textwrap.dedent(
        """\
    manifest-version: '0.1'
    packages:
        bar:
    """
    )

    with pytest.raises(ManifestParseException) as e_info:
        manifest_parser_pkg_foo.parse_manifest(fd=content)

    assert 'package "bar" is not present' in e_info.value.args[0]


def test_create_symlinks_no_list(manifest_parser_pkg_foo):
    content = textwrap.dedent(
        """\
    manifest-version: '0.1'
    packages:
        foo:
            create-symlinks:
                path: a
                target: b
    """
    )

    with pytest.raises(ManifestParseException) as e_info:
        manifest_parser_pkg_foo.parse_manifest(fd=content)

    assert "packages.foo.create-symlinks" in e_info.value.args[0]
    assert "must be a list" in e_info.value.args[0]


def test_create_symlinks_missing_path(manifest_parser_pkg_foo):
    content = textwrap.dedent(
        """\
    manifest-version: '0.1'
    packages:
        foo:
            create-symlinks:
                - missing-path: a
                  target: b
    """
    )

    with pytest.raises(ManifestParseException) as e_info:
        manifest_parser_pkg_foo.parse_manifest(fd=content)

    assert e_info.value.args[0].startswith(
        "Missing required key path at packages.foo.create-symlinks[0]"
    )


def test_create_symlinks_missing_target(manifest_parser_pkg_foo):
    content = textwrap.dedent(
        """\
    manifest-version: '0.1'
    packages:
        foo:
            create-symlinks:
                - path: a
                  missing-target: b
    """
    )

    with pytest.raises(ManifestParseException) as e_info:
        manifest_parser_pkg_foo.parse_manifest(fd=content)

    assert e_info.value.args[0].startswith(
        "Missing required key target at packages.foo.create-symlinks[0]"
    )


def test_create_symlinks_not_normalized_path(manifest_parser_pkg_foo):
    content = textwrap.dedent(
        """\
    manifest-version: '0.1'
    packages:
        foo:
            create-symlinks:
                - path: ../bar
                  target: b
    """
    )

    with pytest.raises(ManifestParseException) as e_info:
        manifest_parser_pkg_foo.parse_manifest(fd=content)

    expected = (
        'The path "../bar" provided in packages.foo.create-symlinks[0] <../bar> should be relative to the root'
        ' of the package and not use any ".." or "." segments.'
    )
    assert e_info.value.args[0] == expected
