from plone import api
from plone.app.testing.helpers import login
from plone.app.testing.interfaces import SITE_OWNER_NAME
from ploneintranet.contacts.browser.app import View
from ploneintranet.contacts.testing import PLONEINTRANET_CONTACTS_INTEGRATION_TESTING
from ploneintranet.search.solr.testing import SOLR_FIXTURE
from urllib.parse import parse_qsl
from zope.annotation import IAnnotations

import lxml
import unittest


class ContactTestCase(unittest.TestCase):
    """Test the contacts app"""

    layer = PLONEINTRANET_CONTACTS_INTEGRATION_TESTING

    def setUp(self):
        login(self.layer["app"], SITE_OWNER_NAME)
        self.portal = self.layer["portal"]
        self.request = self.portal.REQUEST.clone()
        self.app_view = self.get_view()
        SOLR_FIXTURE._solr_restore()

    def get_view(self, name=None, context=None, request=None) -> View:
        if not name:
            name = "app-contacts"
        if not context:
            context = self.portal.apps.contacts
        if not request:
            request = self.request.clone()
        return api.content.get_view(name=name, context=context, request=request)

    def purge_memoize(self, request=None):
        """Purge the memoize cache, stored in the annotations."""
        if not request:
            request = self.app_view.request
        IAnnotations(request).pop("plone.memoize", None)

    def test_no_criteria(self):
        self.assertListEqual(
            [principal.getId for principal in self.app_view.principals()],
            ["hr", "production"],
        )

    def test_pagination(self):
        """The first page has page_idx = 0,
        pagination size can be controlled through the page_size parameter.
        """
        self.assertListEqual(
            [principal.getId for principal in self.app_view.principals()],
            ["hr", "production"],
        )

        self.purge_memoize()

        self.app_view.request.form["page_size"] = 1

        self.assertListEqual(
            [principal.getId for principal in self.app_view.principals()],
            ["hr"],
        )

        self.assertSetEqual(
            set(parse_qsl(self.app_view.query_more)),
            {("page_idx", "1"), ("page_size", "1")},
        )

        self.purge_memoize()

        self.app_view.request.form["page_idx"] = 1

        self.assertListEqual(
            [principal.getId for principal in self.app_view.principals()],
            ["production"],
        )

        self.purge_memoize()

        self.app_view.request.form["page_idx"] = 100
        self.assertListEqual(
            [principal.getId for principal in self.app_view.principals()],
            [],
        )
        self.assertEqual(self.app_view.query_more, "")

    def test_filter_text(self):
        self.app_view.request.form["SearchableText"] = "HR"
        self.assertListEqual(
            [principal.getId for principal in self.app_view.principals()],
            ["hr"],
        )

        self.purge_memoize()

        self.app_view.request.form["SearchableText"] = "Users"

        self.assertListEqual(
            [principal.getId for principal in self.app_view.principals()],
            [],  # intranet suppressed
        )

    def check_behavior_installed(self):
        """Check that the proper indexer behavior is installed on the
        contact type according to the Plone version
        """
        pt = api.portal.get_tool("portal_types")
        fti = pt["ploneintranet.userprofile.contact"]
        behavior_name = "plone.textindexer"
        self.assertIn(behavior_name, fti.behaviors)

    def test_includes_navigation_links(self):
        contacts_container = self.portal.get("contacts", None)
        self.assertIsNotNone(contacts_container)

        api.content.create(
            container=contacts_container,
            type="Link",
            id="link-to-somewhere",
            title="Link to Somewhere",
            remoteUrl="${portal_url}/somewhere",
        )

        nav_links = self.app_view.extra_navigation_items
        self.assertEqual(len(nav_links), 1)
        self.assertEqual(nav_links[0].getId, "link-to-somewhere")

    def test_includes_navigation_links_rendered(self):
        contacts_container = self.portal.get("contacts", None)
        self.assertIsNotNone(contacts_container)

        api.content.create(
            container=contacts_container,
            type="Link",
            id="link-to-somewhere",
            title="Link to Somewhere",
            remoteUrl="${portal_url}/somewhere",
        )

        app = self.portal.apps.contacts
        sidebar = app.restrictedTraverse("@@app-contacts-sidebar")

        tree = lxml.html.fromstring(sidebar())

        nav_el = tree.cssselect("#sidebar-content .item.link-to-somewhere")
        self.assertEqual(len(nav_el), 1)
        link_el = nav_el[0].cssselect("a")
        self.assertEqual(len(link_el), 1)
        self.assertEqual(link_el[0].get("href"), "/plone/somewhere")
        text_el = link_el[0].cssselect(".title")
        self.assertEqual(text_el[0].text.strip(), "Link to Somewhere")
