"""
    :codeauthor: :email:`Gareth J. Greenaway <gareth@saltstack.com>`
    :codeauthor: :email:`David Murphy <dmurphy@saltstack.com>`
"""

import datetime
import time
import types

import pytest
import salt.modules.gpg as gpg
from salt.exceptions import SaltInvocationError
from tests.support.mock import MagicMock, patch

pytest.importorskip("gnupg")

pytestmark = [
    pytest.mark.skip_unless_on_linux,
]

GPG_TEST_KEY_PASSPHRASE = "testkeypassphrase"
GPG_TEST_KEY_ID = "7416F045"
GPG_TEST_PUB_KEY = """-----BEGIN PGP PUBLIC KEY BLOCK-----

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
ylirh0aqUQdSeIuJTg==
=yF8M
-----END PGP PUBLIC KEY BLOCK-----
"""

GPG_TEST_PRIV_KEY = """-----BEGIN PGP PRIVATE KEY BLOCK-----


OZV2Hg+93dg3Wi6g/JW4OuTKWKuHRqpRB1J4i4lO
=WRTN
-----END PGP PRIVATE KEY BLOCK-----
"""


@pytest.fixture
def gpghome(tmp_path):
    root = tmp_path / "gpghome"
    root.mkdir(mode=0o0700)
    pub = root / "gpgfile.pub"
    pub.write_text(GPG_TEST_PUB_KEY)
    priv = root / "gpgfile.priv"
    priv.write_text(GPG_TEST_PRIV_KEY)
    return types.SimpleNamespace(path=root, pub=pub, priv=priv)


@pytest.fixture
def configure_loader_modules(gpghome):
    return {gpg: {}}


def test_list_keys():
    """
    Test gpg.list_keys
    """

    _user_mock = {
        "shell": "/bin/bash",
        "workphone": "",
        "uid": 0,
        "passwd": "x",
        "roomnumber": "",
        "gid": 0,
        "groups": ["root"],
        "home": "/root",
        "fullname": "root",
        "homephone": "",
        "name": "root",
    }

    _list_result = [
        {
            "dummy": "",
            "keyid": "xxxxxxxxxxxxxxxx",
            "expires": "2011188692",
            "sigs": [],
            "subkeys": [
                ["xxxxxxxxxxxxxxxx", "e", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
            ],
            "length": "4096",
            "ownertrust": "-",
            "sig": "",
            "algo": "1",
            "fingerprint": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "date": "1506612692",
            "trust": "-",
            "type": "pub",
            "uids": ["GPG Person <person@example.com>"],
        }
    ]

    _expected_result = [
        {
            "keyid": "xxxxxxxxxxxxxxxx",
            "uids": ["GPG Person <person@example.com>"],
            "created": "2017-09-28",
            "expires": "2033-09-24",
            "keyLength": "4096",
            "ownerTrust": "Unknown",
            "fingerprint": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "trust": "Unknown",
        }
    ]

    mock_opt = MagicMock(return_value="root")
    with patch.dict(gpg.__salt__, {"user.info": MagicMock(return_value=_user_mock)}):
        with patch.dict(gpg.__salt__, {"config.option": mock_opt}):
            with patch.object(gpg, "_list_keys", return_value=_list_result):
                assert gpg.list_keys() == _expected_result


def test_get_key():
    """
    Test gpg.get_key
    """

    _user_mock = {
        "shell": "/bin/bash",
        "workphone": "",
        "uid": 0,
        "passwd": "x",
        "roomnumber": "",
        "gid": 0,
        "groups": ["root"],
        "home": "/root",
        "fullname": "root",
        "homephone": "",
        "name": "root",
    }

    _list_result = [
        {
            "dummy": "",
            "keyid": "xxxxxxxxxxxxxxxx",
            "expires": "2011188692",
            "sigs": [],
            "subkeys": [
                ["xxxxxxxxxxxxxxxx", "e", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
            ],
            "length": "4096",
            "ownertrust": "-",
            "sig": "",
            "algo": "1",
            "fingerprint": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "date": "1506612692",
            "trust": "-",
            "type": "pub",
            "uids": ["GPG Person <person@example.com>"],
        }
    ]

    _expected_result = {
        "fingerprint": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "keyid": "xxxxxxxxxxxxxxxx",
        "uids": ["GPG Person <person@example.com>"],
        "created": "2017-09-28",
        "trust": "Unknown",
        "ownerTrust": "Unknown",
        "expires": "2033-09-24",
        "keyLength": "4096",
    }

    mock_opt = MagicMock(return_value="root")
    with patch.dict(gpg.__salt__, {"user.info": MagicMock(return_value=_user_mock)}):
        with patch.dict(gpg.__salt__, {"config.option": mock_opt}):
            with patch.object(gpg, "_list_keys", return_value=_list_result):
                ret = gpg.get_key("xxxxxxxxxxxxxxxx")
                assert ret == _expected_result


def test_delete_key_without_passphrase(gpghome):
    """
    Test gpg.delete_key without passphrase
    """

    _user_mock = {
        "shell": "/bin/bash",
        "workphone": "",
        "uid": 0,
        "passwd": "x",
        "roomnumber": "",
        "gid": 0,
        "groups": ["root"],
        "home": str(gpghome.path),
        "fullname": "root",
        "homephone": "",
        "name": "root",
    }

    _list_result = [
        {
            "dummy": "",
            "keyid": "xxxxxxxxxxxxxxxx",
            "expires": "2011188692",
            "sigs": [],
            "subkeys": [
                ["xxxxxxxxxxxxxxxx", "e", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
            ],
            "length": "4096",
            "ownertrust": "-",
            "sig": "",
            "algo": "1",
            "fingerprint": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "date": "1506612692",
            "trust": "-",
            "type": "pub",
            "uids": ["GPG Person <person@example.com>"],
        }
    ]

    _expected_result = {
        "res": True,
        "message": (
            "Secret key for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx deleted\nPublic"
            " key for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx deleted"
        ),
    }

    mock_opt = MagicMock(return_value="root")
    with patch.dict(gpg.__salt__, {"user.info": MagicMock(return_value=_user_mock)}):
        with patch.dict(gpg.__salt__, {"config.option": mock_opt}):
            with patch.object(gpg, "_list_keys", return_value=_list_result):
                with patch(
                    "salt.modules.gpg.gnupg.GPG.delete_keys",
                    MagicMock(return_value="ok"),
                ) as gnupg_delete_keys:
                    ret = gpg.delete_key(
                        "xxxxxxxxxxxxxxxx", delete_secret=True, use_passphrase=False
                    )
                    assert ret == _expected_result
                    gnupg_delete_keys.assert_called_with(
                        "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                        False,
                        expect_passphrase=False,
                    )


def test_delete_key_with_passphrase_without_gpg_passphrase_in_pillar(gpghome):
    """
    Test gpg.delete_key with passphrase but without gpg_passphrase pillar
    """

    _user_mock = {
        "shell": "/bin/bash",
        "workphone": "",
        "uid": 0,
        "passwd": "x",
        "roomnumber": "",
        "gid": 0,
        "groups": ["root"],
        "home": str(gpghome.path),
        "fullname": "root",
        "homephone": "",
        "name": "root",
    }

    _list_result = [
        {
            "dummy": "",
            "keyid": "xxxxxxxxxxxxxxxx",
            "expires": "2011188692",
            "sigs": [],
            "subkeys": [
                ["xxxxxxxxxxxxxxxx", "e", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
            ],
            "length": "4096",
            "ownertrust": "-",
            "sig": "",
            "algo": "1",
            "fingerprint": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "date": "1506612692",
            "trust": "-",
            "type": "pub",
            "uids": ["GPG Person <person@example.com>"],
        }
    ]

    _expected_result = {
        "res": True,
        "message": "gpg_passphrase not available in pillar.",
    }

    mock_opt = MagicMock(return_value="root")
    pillar_mock = MagicMock(return_value=None)
    with patch.dict(gpg.__salt__, {"user.info": MagicMock(return_value=_user_mock)}):
        with patch.dict(gpg.__salt__, {"config.option": mock_opt}), patch.dict(
            gpg.__salt__, {"pillar.get": pillar_mock}
        ):
            with patch.object(gpg, "_list_keys", return_value=_list_result):
                with patch(
                    "salt.modules.gpg.gnupg.GPG.delete_keys"
                ) as gnupg_delete_keys:
                    ret = gpg.delete_key("xxxxxxxxxxxxxxxx", delete_secret=True)
                    assert ret == _expected_result
                    gnupg_delete_keys.assert_not_called()


def test_delete_key_with_passphrase_with_gpg_passphrase_in_pillar(gpghome):
    """
    Test gpg.delete_key with passphrase and gpg_passphrase pillar
    """

    _user_mock = {
        "shell": "/bin/bash",
        "workphone": "",
        "uid": 0,
        "passwd": "x",
        "roomnumber": "",
        "gid": 0,
        "groups": ["root"],
        "home": str(gpghome.path),
        "fullname": "root",
        "homephone": "",
        "name": "root",
    }

    _list_result = [
        {
            "dummy": "",
            "keyid": "xxxxxxxxxxxxxxxx",
            "expires": "2011188692",
            "sigs": [],
            "subkeys": [
                ["xxxxxxxxxxxxxxxx", "e", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]
            ],
            "length": "4096",
            "ownertrust": "-",
            "sig": "",
            "algo": "1",
            "fingerprint": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "date": "1506612692",
            "trust": "-",
            "type": "pub",
            "uids": ["GPG Person <person@example.com>"],
        }
    ]

    _expected_result = {
        "res": True,
        "message": (
            "Secret key for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx deleted\nPublic"
            " key for xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx deleted"
        ),
    }

    mock_opt = MagicMock(return_value="root")
    pillar_mock = MagicMock(return_value=GPG_TEST_KEY_PASSPHRASE)
    with patch.dict(gpg.__salt__, {"user.info": MagicMock(return_value=_user_mock)}):
        with patch.dict(gpg.__salt__, {"config.option": mock_opt}), patch.dict(
            gpg.__salt__, {"pillar.get": pillar_mock}
        ):
            with patch.object(gpg, "_list_keys", return_value=_list_result):
                with patch(
                    "salt.modules.gpg.gnupg.GPG.delete_keys",
                    MagicMock(return_value="ok"),
                ) as gnupg_delete_keys:
                    ret = gpg.delete_key("xxxxxxxxxxxxxxxx", delete_secret=True)
                    assert ret == _expected_result
                    gnupg_delete_keys.assert_called_with(
                        "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
                        False,
                        passphrase=GPG_TEST_KEY_PASSPHRASE,
                    )


def test_export_key_without_passphrase(gpghome):
    """
    Test gpg.export_key without passphrase
    """

    _user_mock = {
        "shell": "/bin/bash",
        "workphone": "",
        "uid": 0,
        "passwd": "x",
        "roomnumber": "",
        "gid": 0,
        "groups": ["root"],
        "home": str(gpghome.path),
        "fullname": "root",
        "homephone": "",
        "name": "root",
    }

    mock_opt = MagicMock(return_value="root")
    with patch.dict(gpg.__salt__, {"user.info": MagicMock(return_value=_user_mock)}):
        with patch.dict(gpg.__salt__, {"config.option": mock_opt}):
            with patch(
                "salt.modules.gpg.gnupg.GPG.export_keys",
                MagicMock(return_value=GPG_TEST_PUB_KEY),
            ) as gnupg_export_keys:
                ret = gpg.export_key("xxxxxxxxxxxxxxxx")
                assert ret == GPG_TEST_PUB_KEY
                gnupg_export_keys.assert_called_with(
                    ["xxxxxxxxxxxxxxxx"],
                    False,
                    expect_passphrase=False,
                )


def test_export_multiple_keys_without_passphrase(gpghome):
    """
    Test gpg.export_key with multiple keys and without passphrase
    """

    _user_mock = {
        "shell": "/bin/bash",
        "workphone": "",
        "uid": 0,
        "passwd": "x",
        "roomnumber": "",
        "gid": 0,
        "groups": ["root"],
        "home": str(gpghome.path),
        "fullname": "root",
        "homephone": "",
        "name": "root",
    }

    mock_opt = MagicMock(return_value="root")
    with patch.dict(gpg.__salt__, {"user.info": MagicMock(return_value=_user_mock)}):
        with patch.dict(gpg.__salt__, {"config.option": mock_opt}):
            with patch(
                "salt.modules.gpg.gnupg.GPG.export_keys",
                MagicMock(return_value=GPG_TEST_PUB_KEY),
            ) as gnupg_export_keys:
                ret = gpg.export_key(
                    "xxxxxxxxxxxxxxxx,yyyyyyyyyyyyyyyy,zzzzzzzzzzzzzzzz"
                )
                assert ret == GPG_TEST_PUB_KEY
                gnupg_export_keys.assert_called_with(
                    ["xxxxxxxxxxxxxxxx", "yyyyyyyyyyyyyyyy", "zzzzzzzzzzzzzzzz"],
                    False,
                    expect_passphrase=False,
                )


def test_export_key_with_passphrase_without_gpg_passphrase_in_pillar(gpghome):
    """
    Test gpg.export_key with passphrase but without gpg_passphrase pillar
    """

    _user_mock = {
        "shell": "/bin/bash",
        "workphone": "",
        "uid": 0,
        "passwd": "x",
        "roomnumber": "",
        "gid": 0,
        "groups": ["root"],
        "home": str(gpghome.path),
        "fullname": "root",
        "homephone": "",
        "name": "root",
    }

    mock_opt = MagicMock(return_value="root")
    pillar_mock = MagicMock(return_value=None)
    with patch.dict(gpg.__salt__, {"user.info": MagicMock(return_value=_user_mock)}):
        with patch.dict(gpg.__salt__, {"config.option": mock_opt}), patch.dict(
            gpg.__salt__, {"pillar.get": pillar_mock}
        ):
            with patch(
                "salt.modules.gpg.gnupg.GPG.export_keys",
                MagicMock(return_value=GPG_TEST_PUB_KEY),
            ) as gnupg_export_keys:
                with pytest.raises(SaltInvocationError):
                    assert gpg.export_key("xxxxxxxxxxxxxxxx", use_passphrase=True)
                gnupg_export_keys.assert_not_called()


def test_export_key_with_passphrase_with_gpg_passphrase_in_pillar(gpghome):
    """
    Test gpg.export_key with passphrase and gpg_passphrase pillar
    """

    _user_mock = {
        "shell": "/bin/bash",
        "workphone": "",
        "uid": 0,
        "passwd": "x",
        "roomnumber": "",
        "gid": 0,
        "groups": ["root"],
        "home": str(gpghome.path),
        "fullname": "root",
        "homephone": "",
        "name": "root",
    }

    mock_opt = MagicMock(return_value="root")
    pillar_mock = MagicMock(return_value=GPG_TEST_KEY_PASSPHRASE)
    with patch.dict(gpg.__salt__, {"user.info": MagicMock(return_value=_user_mock)}):
        with patch.dict(gpg.__salt__, {"config.option": mock_opt}), patch.dict(
            gpg.__salt__, {"pillar.get": pillar_mock}
        ):
            with patch(
                "salt.modules.gpg.gnupg.GPG.export_keys",
                MagicMock(return_value=GPG_TEST_PUB_KEY),
            ) as gnupg_export_keys:
                ret = gpg.export_key("xxxxxxxxxxxxxxxx", use_passphrase=True)
                assert ret == GPG_TEST_PUB_KEY
                gnupg_export_keys.assert_called_with(
                    ["xxxxxxxxxxxxxxxx"],
                    False,
                    passphrase=GPG_TEST_KEY_PASSPHRASE,
                )


def test_create_key_without_passphrase(gpghome):
    """
    Test gpg.create_key without a passphrase
    """

    _user_mock = {
        "shell": "/bin/bash",
        "workphone": "",
        "uid": 0,
        "passwd": "x",
        "roomnumber": "",
        "gid": 0,
        "groups": ["root"],
        "home": str(gpghome.path),
        "fullname": "root",
        "homephone": "",
        "name": "root",
    }

    mock_opt = MagicMock(return_value="root")
    with patch.dict(gpg.__salt__, {"user.info": MagicMock(return_value=_user_mock)}):
        with patch.dict(gpg.__salt__, {"config.option": mock_opt}):
            ret = gpg.create_key()
            assert ret["res"]
            assert ret["fingerprint"]
            assert ret["message"] == "GPG key pair successfully generated."


def test_create_key_with_passphrase_without_gpg_passphrase_in_pillar(gpghome):
    """
    Test gpg.create_key with passphrase but without gpg_passphrase pillar
    """

    _user_mock = {
        "shell": "/bin/bash",
        "workphone": "",
        "uid": 0,
        "passwd": "x",
        "roomnumber": "",
        "gid": 0,
        "groups": ["root"],
        "home": str(gpghome.path),
        "fullname": "root",
        "homephone": "",
        "name": "root",
    }

    mock_opt = MagicMock(return_value="root")
    pillar_mock = MagicMock(return_value=None)
    with patch.dict(gpg.__salt__, {"user.info": MagicMock(return_value=_user_mock)}):
        with patch.dict(gpg.__salt__, {"config.option": mock_opt}), patch.dict(
            gpg.__salt__, {"pillar.get": pillar_mock}
        ):
            ret = gpg.create_key(use_passphrase=True)
            assert not ret["res"]
            assert ret["message"] == "gpg_passphrase not available in pillar."


def test_create_key_with_passphrase_with_gpg_passphrase_in_pillar(gpghome):
    """
    Test gpg.create_key with passphrase and gpg_passphrase pillar
    """

    _user_mock = {
        "shell": "/bin/bash",
        "workphone": "",
        "uid": 0,
        "passwd": "x",
        "roomnumber": "",
        "gid": 0,
        "groups": ["root"],
        "home": str(gpghome.path),
        "fullname": "root",
        "homephone": "",
        "name": "root",
    }

    mock_opt = MagicMock(return_value="root")
    pillar_mock = MagicMock(return_value=GPG_TEST_KEY_PASSPHRASE)
    with patch.dict(gpg.__salt__, {"user.info": MagicMock(return_value=_user_mock)}):
        with patch.dict(gpg.__salt__, {"config.option": mock_opt}), patch.dict(
            gpg.__salt__, {"pillar.get": pillar_mock}
        ):
            ret = gpg.create_key(use_passphrase=True)
            assert ret["res"]
            assert ret["fingerprint"]
            assert ret["message"] == "GPG key pair successfully generated."


def test_search_keys(gpghome):
    """
    Test gpg.search_keys
    """

    _user_mock = {
        "shell": "/bin/bash",
        "workphone": "",
        "uid": 0,
        "passwd": "x",
        "roomnumber": "",
        "gid": 0,
        "groups": ["root"],
        "home": str(gpghome.path),
        "fullname": "root",
        "homephone": "",
        "name": "root",
    }

    _search_result = [
        {
            "keyid": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "uids": ["GPG Person <person@example.com>"],
            "expires": "",
            "sigs": [],
            "length": "1024",
            "algo": "17",
            "date": int(time.mktime(datetime.datetime(2004, 11, 13).timetuple())),
            "type": "pub",
        }
    ]

    _expected_result = [
        {
            "uids": ["GPG Person <person@example.com>"],
            "created": "2004-11-13",
            "keyLength": "1024",
            "keyid": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        }
    ]

    mock_opt = MagicMock(return_value="root")
    with patch.dict(gpg.__salt__, {"user.info": MagicMock(return_value=_user_mock)}):
        with patch.dict(gpg.__salt__, {"config.option": mock_opt}):
            with patch.object(gpg, "_search_keys", return_value=_search_result):
                ret = gpg.search_keys("person@example.com")
                assert ret == _expected_result


def test_gpg_import_pub_key(gpghome):
    config_user = MagicMock(return_value="salt")
    user_info = MagicMock(
        return_value={"name": "salt", "home": str(gpghome.path), "uid": 1000}
    )
    with patch.dict(gpg.__salt__, {"config.option": config_user}):
        with patch.dict(gpg.__salt__, {"user.info": user_info}):
            ret = gpg.import_key(None, str(gpghome.pub), "salt", str(gpghome.path))
            assert ret["res"] is True


def test_gpg_import_priv_key(gpghome):
    config_user = MagicMock(return_value="salt")
    user_info = MagicMock(
        return_value={"name": "salt", "home": str(gpghome.path), "uid": 1000}
    )
    with patch.dict(gpg.__salt__, {"config.option": config_user}):
        with patch.dict(gpg.__salt__, {"user.info": user_info}):
            ret = gpg.import_key(None, str(gpghome.priv), "salt", str(gpghome.path))
            assert ret["res"] is True


def test_gpg_sign(gpghome):
    config_user = MagicMock(return_value="salt")
    user_info = MagicMock(
        return_value={"name": "salt", "home": str(gpghome.path), "uid": 1000}
    )
    pillar_mock = MagicMock(return_value={"gpg_passphrase": GPG_TEST_KEY_PASSPHRASE})
    with patch.dict(gpg.__salt__, {"config.option": config_user}):
        with patch.dict(gpg.__salt__, {"user.info": user_info}):
            with patch.dict(gpg.__salt__, {"pillar.get": pillar_mock}):
                ret = gpg.import_key(None, str(gpghome.priv), "salt", str(gpghome.path))
                assert ret["res"] is True
                gpg_text_input = "The quick brown fox jumped over the lazy dog"
                gpg_sign_output = gpg.sign(
                    config_user,
                    GPG_TEST_KEY_ID,
                    gpg_text_input,
                    None,
                    None,
                    True,
                    str(gpghome.path),
                )
                assert gpg_sign_output is not None
