from plone import api
from ploneintranet import api as pi_api
from ploneintranet.api.tests.mocks import FakeUserprofile
from ploneintranet.search.testing import IntegrationTestCase
from unittest import mock

import locale

PROJECTNAME = "ploneintranet.search"


class BaseSearchTestCase(IntegrationTestCase):
    """Base test case we need to test the views"""

    def setUp(self):
        super().setUp()
        self.portal = self.layer["portal"]

    def get_search_view(self, params={}):
        """Return the search view called with params"""
        request = self.layer["request"].clone()
        request.form.update(params)
        return api.content.get_view("search", self.portal, request)


class TestSearchView(BaseSearchTestCase):
    """Test search view functionality"""

    def test_sorting_method(self):
        """The function we use for sorting items that have a title"""
        view = self.get_search_view()
        old_locale = locale.getlocale(locale.LC_COLLATE)
        # make the tests indipendent from the environment
        locale.setlocale(locale.LC_COLLATE, ("en_US", "UTF-8"))
        items = [
            {"title": "A"},
            {"title": "B"},
            {"title": "c"},
            {"title": "sr"},
            {"title": "st"},
            {"title": "z"},
            {"title": "ß"},
            {"title": "à"},
            {"title": "ä"},
        ]

        # now sort the items with the methods provided by the view
        items.sort(key=view.sorting_key_item_title)

        self.assertListEqual(
            items,
            [
                {"title": "A"},
                {"title": "à"},
                {"title": "ä"},
                {"title": "B"},
                {"title": "c"},
                {"title": "sr"},
                {"title": "ß"},
                {"title": "st"},
                {"title": "z"},
            ],
        )
        # reset the locale
        locale.setlocale(locale.LC_COLLATE, old_locale)

    def test_exclusion(self):
        view = self.get_search_view()
        filters = view.get_filters()
        self.assertIn(
            "ploneintranet.search.interfaces.IExcludeFromSearchResults",
            filters.get("!object_provides"),
        )


class TestSearchOptionsPersistent(BaseSearchTestCase):
    def setUp(self):
        super().setUp()

    def test_defaults_not_modified_vanilla(self):
        """If the user accepts the defaults, we are not storing anything on it"""
        with mock.patch(
            "ploneintranet.api.userprofile.get_current", return_value=FakeUserprofile()
        ):
            user = pi_api.userprofile.get_current()
            view = self.get_search_view()
            self.assertEqual(view.display_previews(), True)
            self.assertEqual(view.get_sorting(), None)
            self.assertFalse(hasattr(user, "display_previews"))
            self.assertFalse(hasattr(user, "search_sorting"))

    def test_options_persist(self):
        """If the user accepts the defaults, we are not storing anything on it"""
        with mock.patch(
            "ploneintranet.api.userprofile.get_current", return_value=FakeUserprofile()
        ):
            user = pi_api.userprofile.get_current()
            # First we call the view with non default parameter
            view = self.get_search_view(
                {
                    "SearchableText": "x",
                    "filtering": "on",
                    "display-previews": "off",
                    "results-sorting": "date",
                    "options.submitted": 1,
                }
            )
            self.assertFalse(view.display_previews(), False)
            self.assertEqual(view.get_sorting(), "-created")
            self.assertEqual(user.display_previews, "off")
            self.assertEqual(user.search_sorting, "date")

            # Then with no parameters and see that the options persist
            view = self.get_search_view()
            self.assertFalse(view.display_previews(), False)
            self.assertEqual(view.get_sorting(), "-created")
            self.assertEqual(user.display_previews, "off")
            self.assertEqual(user.search_sorting, "date")

        # If we change use we have the default options
        with mock.patch(
            "ploneintranet.api.userprofile.get_current", return_value=FakeUserprofile()
        ):
            user = pi_api.userprofile.get_current()
            view = self.get_search_view()
            self.assertEqual(view.display_previews(), True)
            self.assertEqual(view.get_sorting(), None)
            self.assertFalse(hasattr(user, "display_previews"))
            self.assertFalse(hasattr(user, "search_sorting"))

            # But we can manipulate them opertaing on the user
            user.display_previews = "off"
            user.search_sorting = "date"
            view = self.get_search_view()
            self.assertFalse(view.display_previews(), False)
            self.assertEqual(view.get_sorting(), "-created")
            self.assertEqual(user.display_previews, "off")
            self.assertEqual(user.search_sorting, "date")

    def tearDown(self):
        super().tearDown()
