"""
    :codeauthor: Jayesh Kariya <jayeshk@saltstack.com>

    Test cases for salt.modules.solr
"""

import os

import pytest

import salt.modules.solr as solr
from tests.support.mock import MagicMock, patch


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


def test_lucene_version():
    """
    Test to get the lucene version that solr is using.
    """
    with patch.object(solr, "_get_return_dict", return_value={"A": "a"}):
        with patch.object(solr, "_get_none_or_value", side_effect=[None, True, True]):
            with patch.object(
                solr, "_check_for_cores", side_effect=[True, False, False]
            ):
                tempdict = {
                    "success": "success",
                    "errors": "errors",
                    "data": {"lucene": {"lucene-spec-version": 1}},
                }
                with patch.object(
                    solr,
                    "_get_admin_info",
                    side_effect=[tempdict, tempdict, {"success": None}],
                ):
                    with patch.dict(
                        solr.__salt__,
                        {"config.option": MagicMock(return_value=["A"])},
                    ):

                        with patch.object(
                            solr, "_update_return_dict", return_value={"A": "a"}
                        ):
                            assert solr.lucene_version("c") == {"A": "a"}

                        assert solr.lucene_version("c") == {"A": "a"}

                        assert solr.lucene_version("c") == {"success": None}


def test_version():
    """
    Test to get the solr version for the core specified
    """
    with patch.object(solr, "_get_return_dict", return_value={"A": "a"}):
        with patch.object(solr, "_get_none_or_value", side_effect=[None, True, True]):
            with patch.object(
                solr, "_check_for_cores", side_effect=[True, False, False]
            ):

                tempdict = {
                    "success": "success",
                    "errors": "errors",
                    "warnings": "warnings",
                    "data": {"lucene": {"solr-spec-version": 1}},
                }
                with patch.object(
                    solr, "_get_admin_info", side_effect=[tempdict, tempdict]
                ):
                    with patch.dict(
                        solr.__opts__, {"solr.cores": MagicMock(return_value=["A"])}
                    ):
                        with patch.object(
                            solr, "_update_return_dict", return_value={"A": "a"}
                        ):
                            assert solr.version() == {"A": "a"}

                        assert solr.version() == {"A": "a"}

                with patch.object(
                    solr, "_get_admin_info", return_value={"success": None}
                ):
                    assert solr.version() == {"success": None}


def test_optimize():
    """
    Test to search queries fast, but it is a very expensive operation.
    """
    with patch.object(solr, "_get_return_dict", return_value={"A": "a"}):
        with patch.object(solr, "_get_none_or_value", side_effect=[None, True]):
            with patch.object(solr, "_check_for_cores", side_effect=[True, False]):
                tempdict = {
                    "success": "success",
                    "errors": "errors",
                    "warnings": "warnings",
                    "data": {"lucene": {"solr-spec-version": 1}},
                }
                with patch.object(solr, "_format_url", return_value="A"):
                    with patch.dict(
                        solr.__salt__,
                        {"config.option": MagicMock(return_value=["A"])},
                    ):
                        with patch.object(solr, "_http_request", return_value=tempdict):
                            with patch.object(
                                solr, "_update_return_dict", return_value={"A": "a"}
                            ):
                                assert solr.optimize() == {"A": "a"}

                    with patch.object(solr, "_http_request", return_value="A"):
                        assert solr.optimize() == "A"


def test_ping():
    """
    Test to check on solr, makes sure solr can talk to the
    indexes.
    """
    with patch.object(solr, "_get_return_dict", return_value={"A": "a"}):
        with patch.object(solr, "_get_none_or_value", side_effect=[None, True]):
            with patch.object(solr, "_check_for_cores", side_effect=[True, False]):

                tempdict = {
                    "success": "success",
                    "errors": "errors",
                    "warnings": "warnings",
                    "data": {"lucene": {"solr-spec-version": 1}},
                }

                with patch.dict(
                    solr.__opts__, {"solr.cores": MagicMock(return_value=["A"])}
                ):
                    with patch.object(solr, "_get_admin_info", return_value=tempdict):
                        with patch.object(
                            solr, "_update_return_dict", return_value={"A": "a"}
                        ):
                            assert solr.ping() == {"A": "a"}

                with patch.object(solr, "_get_admin_info", return_value="A"):
                    assert solr.ping() == "A"


def test_is_replication_enabled():
    """
    Test to check for errors, and determine if a slave
    is replicating or not.
    """
    error = 'Only "slave" minions can run "is_replication_enabled"'
    with patch.object(solr, "_get_return_dict", return_value={"A": "a"}):
        with patch.object(solr, "_is_master", side_effect=[True, False]):
            assert solr.is_replication_enabled() is None
            with patch.object(solr, "_get_none_or_value", return_value=None):
                with patch.object(solr, "_check_for_cores", return_value=True):
                    with patch.dict(
                        solr.__opts__, {"solr.cores": MagicMock(return_value="A")}
                    ):
                        with patch.object(
                            solr, "_replication_request", return_value="A"
                        ):
                            assert solr.is_replication_enabled() == {
                                "A": "a",
                                "errors": [error],
                                "success": False,
                            }


def test_match_index_versions():
    """
    Test to verifies that the master and the slave versions are in sync by
    comparing the index version.
    """
    err = 'solr.match_index_versions can only be called by "slave" minions'
    with patch.object(solr, "_get_return_dict", return_value={"A": "a"}):
        with patch.object(solr, "_is_master", side_effect=[True, False]):

            assert solr.match_index_versions() is None

            with patch.object(solr, "_get_none_or_value", return_value=None):
                with patch.object(solr, "_check_for_cores", return_value=True):
                    with patch.dict(
                        solr.__opts__, {"solr.cores": MagicMock(return_value="A")}
                    ):
                        with patch.object(
                            solr, "_replication_request", return_value="A"
                        ):
                            assert solr.match_index_versions() == {
                                "A": "a",
                                "errors": [err],
                                "success": False,
                            }


def test_replication_details():
    """
    Test to get the full replication details.
    """
    tempdict1 = {
        "success": "success",
        "errors": "errors",
        "warnings": "warnings",
        "data": "data",
    }

    tempdict2 = {
        "success": None,
        "errors": "errors",
        "warnings": "warnings",
        "data": "data",
    }

    with patch.object(solr, "_get_return_dict", return_value={"A": "a"}):
        with patch.object(solr, "_get_none_or_value", return_value=True):
            with patch.object(
                solr, "_replication_request", side_effect=[tempdict2, tempdict1]
            ):

                assert solr.replication_details() == tempdict2

                with patch.object(solr, "_update_return_dict", return_value=tempdict1):
                    assert solr.replication_details() == tempdict1


def test_backup():
    """
    Test to tell solr make a backup.
    """
    tempdict = {
        "success": "success",
        "errors": "errors",
        "warnings": "warnings",
        "data": "data",
    }

    with patch.object(solr, "_get_return_dict", return_value={"A": "a"}):
        with patch.dict(
            solr.__opts__,
            {
                "solr.backup_path": MagicMock(return_value="A"),
                "solr.num_backups": MagicMock(return_value="B"),
                "solr.cores": MagicMock(return_value=["A"]),
            },
        ):
            with patch.object(os.path, "sep", return_value="B"):
                with patch.object(solr, "_get_none_or_value", side_effect=[None, True]):
                    with patch.object(
                        solr, "_check_for_cores", side_effect=[True, False]
                    ):
                        with patch.object(
                            solr, "_replication_request", return_value=tempdict
                        ):
                            with patch.dict(
                                solr.__opts__,
                                {"solr.cores": MagicMock(return_value=["A"])},
                            ):
                                with patch.object(
                                    solr, "_update_return_dict", return_value="A"
                                ):
                                    assert solr.backup() == {"A": "a"}

                            assert solr.backup() == tempdict


def test_set_is_polling():
    """
    Test to prevent the slaves from polling the master for updates.
    """
    tempdict = {
        "success": "success",
        "errors": "errors",
        "warnings": "warnings",
        "data": "data",
    }

    err = 'solr.set_is_polling can only be called by "slave" minions'

    with patch.object(solr, "_get_return_dict", return_value={"A": "a"}):
        with patch.object(solr, "_is_master", side_effect=[True, False, False]):
            with patch.object(
                solr, "_get_none_or_value", side_effect=[None, None, True]
            ):
                with patch.object(solr, "_check_for_cores", side_effect=[True, False]):

                    assert solr.set_is_polling("p") is None

                    with patch.dict(
                        solr.__opts__, {"solr.cores": MagicMock(return_value="A")}
                    ):
                        with patch.object(
                            solr, "_update_return_dict", return_value=tempdict
                        ):
                            assert solr.set_is_polling("p") == {
                                "A": "a",
                                "errors": [err],
                                "success": False,
                            }

                    with patch.object(solr, "_replication_request", return_value="A"):
                        assert solr.set_is_polling("p") == "A"


def test_set_replication_enabled():
    """
    Test to sets the master to ignore poll requests from the slaves.
    """
    with patch.object(solr, "_is_master", side_effect=[False, True, True, True]):
        with patch.object(
            solr, "_get_none_or_value", side_effect=[None, None, True, True, True]
        ):
            with patch.object(solr, "_get_return_dict", side_effect=[{"A": "a"}, {}]):
                with patch.object(solr, "_replication_request", return_value="A"):
                    assert solr.set_replication_enabled("s") == {"A": "a"}
                    with patch.object(solr, "_check_for_cores", return_value=True):
                        with patch.dict(
                            solr.__opts__,
                            {"solr.cores": MagicMock(return_value="n")},
                        ):
                            assert solr.set_replication_enabled("s") == {}
                    assert solr.set_replication_enabled("s") == "A"
                    assert solr.set_replication_enabled(False) == "A"


def test_signal():
    """
    Test to signals Apache Solr to start, stop, or restart.
    """
    assert (
        solr.signal("signal")
        == "signal is an invalid signal. Try: one of: start, stop or restart"
    )


def test_reload_core():
    """
    Test to load a new core from the same configuration as
    an existing registered core.
    """
    error = ['solr.reload_core can only be called by "multi-core" minions']
    with patch.object(solr, "_check_for_cores", side_effect=[False, True, True, True]):
        with patch.object(solr, "_get_none_or_value", side_effect=[None, True]):
            with patch.object(solr, "_get_return_dict", return_value={"A": "a"}):
                with patch.object(solr, "_format_url", return_value="A"):
                    with patch.object(solr, "_http_request", return_value="A"):
                        with patch.dict(
                            solr.__opts__,
                            {"solr.cores": MagicMock(return_value="n")},
                        ):
                            assert solr.reload_core() is None
                            assert solr.reload_core() == {
                                "A": "a",
                                "errors": error,
                                "success": False,
                            }
                            assert solr.reload_core() == "A"


def test_core_status():
    """
    Test to get the status for a given core or all cores
    if no core is specified
    """
    error = ['solr.reload_core can only be called by "multi-core" minions']
    with patch.object(solr, "_check_for_cores", side_effect=[False, True, True, True]):
        with patch.object(solr, "_get_none_or_value", side_effect=[None, True]):
            with patch.object(solr, "_get_return_dict", return_value={"A": "a"}):
                with patch.object(solr, "_format_url", return_value="A"):
                    with patch.object(solr, "_http_request", return_value="A"):
                        with patch.dict(
                            solr.__opts__,
                            {"solr.cores": MagicMock(return_value="n")},
                        ):
                            assert solr.core_status() is None
                            assert solr.core_status() == {
                                "A": "a",
                                "errors": error,
                                "success": False,
                            }

                            assert solr.core_status() == "A"


def test_reload_import_config():
    """
    Test to re-loads the handler config XML file.
    """
    with patch.object(solr, "_is_master", side_effect=[False, True, True]):
        with patch.object(
            solr, "_get_none_or_value", side_effect=[None, None, None, True, True]
        ):
            with patch.object(solr, "_get_return_dict", return_value={"A": "a"}):
                with patch.object(solr, "_check_for_cores", side_effect=[True, False]):
                    with patch.object(solr, "_format_url", return_value="A"):
                        with patch.object(solr, "_http_request", return_value="A"):
                            assert solr.reload_import_config("h") == {"A": "a"}
                            assert solr.reload_import_config("h") == {"A": "a"}
                            assert solr.reload_import_config("h") == "A"


def test_abort_import():
    """
    Test to aborts an existing import command to the specified handler.
    """
    with patch.object(solr, "_is_master", side_effect=[False, True, True]):
        with patch.object(
            solr, "_get_none_or_value", side_effect=[None, None, None, True, True]
        ):
            with patch.object(solr, "_get_return_dict", return_value={"A": "a"}):
                with patch.object(solr, "_check_for_cores", side_effect=[True, False]):
                    with patch.object(solr, "_format_url", return_value="A"):
                        with patch.object(solr, "_http_request", return_value="A"):
                            assert solr.abort_import("h") == {"A": "a"}
                            assert solr.abort_import("h") == {"A": "a"}
                            assert solr.abort_import("h") == "A"


def test_full_import():
    """
    Test to submits an import command to the specified handler using
    specified options.
    """
    with patch(
        "salt.modules.solr._format_url", MagicMock(return_value="A")
    ), patch.object(
        solr, "_is_master", side_effect=[False, True, True, True, True, True]
    ), patch.object(
        solr, "_get_return_dict", return_value={"A": "a"}
    ), patch.object(
        solr, "_get_none_or_value", side_effect=[None, True, True, True, True]
    ), patch.object(
        solr, "_check_for_cores", side_effect=[True, False, False, False, False]
    ), patch.object(
        solr,
        "_pre_index_check",
        side_effect=[{"success": False}, {"success": True}, {"success": True}],
    ), patch.object(
        solr, "_merge_options", side_effect=[{"clean": True}, {"clean": False}]
    ), patch.object(
        solr, "set_replication_enabled", return_value={"success": False}
    ), patch.object(
        solr, "_http_request", return_value="A"
    ):

        assert solr.full_import("h") == {"A": "a"}
        assert solr.full_import("h") == {"A": "a"}
        assert solr.full_import("h") == {"success": False}
        assert solr.full_import("h") == {"A": "a"}
        assert solr.full_import("h") == "A"


def test_delta_import():
    """
    Test to submits an import command to the specified handler using
    specified options.
    """
    with patch(
        "salt.modules.solr._format_url", MagicMock(return_value="A")
    ), patch.object(
        solr, "_is_master", side_effect=[False, True, True, True, True]
    ), patch.object(
        solr, "_get_none_or_value", side_effect=[None, True, True, True, True]
    ), patch.object(
        solr, "_get_return_dict", return_value={"A": "a"}
    ), patch.object(
        solr,
        "_pre_index_check",
        side_effect=[
            {"success": False},
            {"success": True},
            {"success": True},
            {"success": True},
        ],
    ), patch.object(
        solr, "_merge_options", side_effect=[{"clean": True}, {"clean": False}]
    ), patch.object(
        solr, "_check_for_cores", side_effect=[True, False]
    ), patch.object(
        solr, "set_replication_enabled", return_value={"success": False}
    ), patch.object(
        solr, "_http_request", return_value="A"
    ):

        assert solr.delta_import("h") == {"A": "a"}
        assert solr.delta_import("h") == {"success": False}
        assert solr.delta_import("h") == {"A": "a"}
        assert solr.delta_import("h") == "A"


def test_import_status():
    """
    Test to submits an import command to the specified handler using
    specified options.
    """
    with patch.object(solr, "_is_master", side_effect=[False, True]):
        with patch.object(solr, "_get_none_or_value", side_effect=[None, True]):
            with patch.object(solr, "_get_return_dict", return_value={"A": "a"}):
                with patch.object(solr, "_format_url", return_value="A"):
                    with patch.object(solr, "_http_request", return_value="A"):
                        assert solr.import_status("h") == {"A": "a"}
                        assert solr.import_status("h") == "A"
