"""
Tests for ploneintranet.workspace forms
"""

from datetime import datetime
from plone import api
from plone.app.testing import TEST_USER_ID
from ploneintranet import api as pi_api
from ploneintranet.workspace.tests.base import BaseTestCase
from z3c.relationfield import RelationValue
from zope.component import getUtility
from zope.event import notify
from zope.intid.interfaces import IIntIds
from zope.lifecycleevent import ObjectModifiedEvent


class TestWorkspaceSort(BaseTestCase):
    def setUp(self):
        super().setUp()
        # Create a user profile for the test user
        pi_api.userprofile.create(TEST_USER_ID, approve=True)

    def get_workspaces_view(self, context=None, request=None):
        """Return the workspaces view"""
        if not context:
            context = self.workspace_container
        if not request:
            request = self.request.clone()
        return api.content.get_view(
            name="workspaces.html", context=context, request=request
        )

    def test_workspace_sort(self):
        workspaces = self.portal.workspaces
        for sort_by in ("active", "alphabet", "newest"):
            request = self.request.clone()
            request.sort = sort_by
            view = self.get_workspaces_view(workspaces, request)
            self.assertEqual(len(view.sort_options()), 3)
            self.assertEqual(view.sort_options()[0]["value"], "alphabet")

    def test_my_workspaces(self):
        ws_before = self.get_workspaces_view().get_workspaces()
        api.content.create(
            self.workspace_container,
            "ploneintranet.workspace.workspacefolder",
            "example-workspace",
        )
        self.solr_commit()
        ws_after = self.get_workspaces_view().get_workspaces()
        self.assertEqual(len(ws_after) - len(ws_before), 1)

    def test_my_workspaces_sorting(self):
        """This will test that:

        - sorting by default is by sortable_title
        - it can be by modification date (reversed)
        - it can be by activity date (reversed)
        - it can take any value and will not fail
        """
        workspace_container = self.workspace_container
        # Remove the default demo workspace that gets in the way
        api.content.delete(workspace_container["demo-workspace"])
        # create dummy stuff
        superspace1 = api.content.create(
            self.workspace_container,
            "ploneintranet.workspace.superspace",
            title="Superspace 1",
        )
        superspace1.creation_date = datetime.strptime("2014/03/01", "%Y/%m/%d")
        superspace1.modification_date = datetime.strptime("2014/03/01", "%Y/%m/%d")
        superspace1.reindexObject(idxs=["created", "modified"])
        obj1 = api.content.create(
            workspace_container,
            "ploneintranet.workspace.workspacefolder",
            "sort1",
            title="Sortable 1",
        )
        obj1.creation_date = datetime.strptime("2015/01/01", "%Y/%m/%d")
        obj1.modification_date = datetime.strptime("2015/01/01", "%Y/%m/%d")
        obj1.reindexObject(idxs=["created", "modified"])
        obj2 = api.content.create(
            workspace_container,
            "ploneintranet.workspace.workspacefolder",
            "sort2",
            title="Sortable 2",
        )
        obj2.creation_date = datetime.strptime("2016/01/01", "%Y/%m/%d")
        obj2.modification_date = datetime.strptime("2016/01/01", "%Y/%m/%d")
        obj2.reindexObject(idxs=["created", "modified"])
        obj3 = api.content.create(
            workspace_container,
            "ploneintranet.workspace.workspacefolder",
            "sort3",
            title="Sortable 3",
        )
        obj3.creation_date = datetime.strptime("2015/07/01", "%Y/%m/%d")
        obj3.modification_date = datetime.strptime("2015/07/01", "%Y/%m/%d")

        # Create some status updates
        pi_api.microblog.statusupdate.create("test 3", microblog_context=obj3)
        obj3.reindexObject(idxs=["created", "modified"])

        # Add a workspace to the superspace. This should mark the superspace as modified
        request = self.request.clone()
        request.form = {
            "title": "Subspace",
            "description": "test",
            "workspace-type": "private",
            "superspace": superspace1.UID(),
            "form.buttons.create": "Create",
        }
        self.workspace_container.REQUEST = request
        api.content.get_view(
            name="add_workspace", context=self.workspace_container, request=request
        )()

        # Check default query
        self.solr_commit()
        view = self.get_workspaces_view(workspace_container)
        response = view.get_workspaces()
        self.assertListEqual(
            [item["title"] for item in response],
            ["Sortable 1", "Sortable 2", "Sortable 3", "Superspace 1"],
        )

        # Check sort=alphabet
        request = self.request.clone()
        request.form["sort"] = "alphabet"
        view = self.get_workspaces_view(workspace_container, request)
        response = view.get_workspaces()
        self.assertListEqual(
            [item["title"] for item in response],
            ["Sortable 1", "Sortable 2", "Sortable 3", "Superspace 1"],
        )

        # Check sort=newest
        request = self.request.clone()
        request.form["sort"] = "newest"
        view = self.get_workspaces_view(workspace_container, request)
        response = view.get_workspaces()
        self.assertListEqual(
            [item["title"] for item in response],
            ["Sortable 2", "Sortable 3", "Sortable 1", "Superspace 1"],
        )

        # Check sort=activity
        request = self.request.clone()
        request.form["sort"] = "activity"
        view = self.get_workspaces_view(workspace_container, request)
        response = view.get_workspaces()
        self.assertListEqual(
            [item["title"] for item in response],
            ["Superspace 1", "Sortable 3", "Sortable 2", "Sortable 1"],
        )

    def test_modified_workspace_updates_superspace(self):
        workspace_container = self.workspace_container
        # Remove the default demo workspace that gets in the way
        api.content.delete(workspace_container["demo-workspace"])
        # create dummy stuff
        superspace1 = api.content.create(
            self.workspace_container,
            "ploneintranet.workspace.superspace",
            title="Superspace 1",
        )

        intids = getUtility(IIntIds)
        superspace1_relation = RelationValue(intids.getId(superspace1))
        superspace2 = api.content.create(
            self.workspace_container,
            "ploneintranet.workspace.superspace",
            title="Superspace 2",
            superspace=superspace1_relation,
        )

        superspace2_relation = RelationValue(intids.getId(superspace2))
        ws1 = api.content.create(
            workspace_container,
            "ploneintranet.workspace.workspacefolder",
            "inner-workspace",
            title="Inner Workspace",
            superspace=superspace2_relation,
        )

        ws2 = api.content.create(
            workspace_container,
            "ploneintranet.workspace.workspacefolder",
            "outer-workspace",
            title="Outer Workspace",
        )

        superspace1.modification_date = datetime(2014, 3, 1)
        superspace1.reindexObject(idxs=["modified"])
        superspace2.modification_date = datetime(2014, 3, 2)
        superspace2.reindexObject(idxs=["modified"])
        ws1.modification_date = datetime(2014, 3, 3)
        ws1.reindexObject(idxs=["modified"])
        ws2.modification_date = datetime(2015, 1, 1)
        ws2.reindexObject(idxs=["modified"])

        self.solr_commit()
        request = self.request.clone()
        request.form["sort"] = "activity"
        view = self.get_workspaces_view(workspace_container, request)
        response = view.get_workspaces()
        self.assertListEqual(
            [item["title"] for item in response],
            ["Outer Workspace", "Superspace 1"],
        )

        pi_api.microblog.statusupdate.create("test update", microblog_context=ws1)
        notify(ObjectModifiedEvent(ws1))

        self.solr_commit()
        request = self.request.clone()
        request.form["sort"] = "activity"
        view = self.get_workspaces_view(workspace_container, request)
        response = view.get_workspaces()
        self.assertListEqual(
            [item["title"] for item in response],
            ["Superspace 1", "Outer Workspace"],
        )

    def test_my_workspaces_limit(self):
        """This will test that with a limit parameter we slice the results"""
        workspace_container = self.workspace_container
        # Remove the default demo workspace that gets in the way
        api.content.delete(workspace_container["demo-workspace"])
        # create dummy stuff
        api.content.create(
            workspace_container,
            "ploneintranet.workspace.workspacefolder",
            "sort1",
            title="Sortable 1",
        )
        api.content.create(
            workspace_container,
            "ploneintranet.workspace.workspacefolder",
            "sort2",
            title="Sortable 2",
        )
        # Check default query
        self.solr_commit()
        view = self.get_workspaces_view(workspace_container)
        response = view.get_workspaces()

        self.assertListEqual(
            [item["title"] for item in response], ["Sortable 1", "Sortable 2"]
        )

        # Check with a broken limit
        request = self.request.clone()
        request.form["limit"] = "broken limit"
        view = self.get_workspaces_view(workspace_container, request)
        response = view.get_workspaces()
        self.assertListEqual(
            [item["title"] for item in response], ["Sortable 1", "Sortable 2"]
        )

        # Check with a working limit
        request = self.request.clone()
        request.form["limit"] = "1"
        view = self.get_workspaces_view(workspace_container, request)
        response = view.get_workspaces()
        self.assertListEqual([item["title"] for item in response], ["Sortable 1"])

    def test_my_workspaces_superspaces(self):
        # Remove the default demo workspace that gets in the way
        api.content.delete(self.workspace_container["demo-workspace"])
        # Create an intranet user
        pi_api.userprofile.create(username="demo", approve=True)

        superspace_1 = api.content.create(
            self.workspace_container,
            "ploneintranet.workspace.superspace",
            title="Superspace 1",
        )
        self.solr_commit()
        view = self.get_workspaces_view()
        # I can always see my superspaces
        self.assertListEqual(
            [x["title"] for x in view.get_workspaces()], ["Superspace 1"]
        )
        # another user cannot if they are empty
        view.request = self.request.clone()
        intids = getUtility(IIntIds)
        superspace_1_relation = RelationValue(intids.getId(superspace_1))
        with api.env.adopt_user("demo"):
            self.assertListEqual(view.get_workspaces(), [])
            # but he can anyway add a subspace
            api.content.create(
                self.workspace_container,
                "ploneintranet.workspace.workspacefolder",
                title="Demo subspace 1",
                superspace=superspace_1_relation,
            )
            self.solr_commit()
            view.request = self.request.clone()
            self.assertListEqual(
                [x["title"] for x in view.get_workspaces()], ["Superspace 1"]
            )
        # sub superspaces should not be visible
        api.content.create(
            self.workspace_container,
            "ploneintranet.workspace.superspace",
            title="Sub superspace 1",
            superspace=superspace_1_relation,
        )
        self.solr_commit()
        self.assertListEqual(
            [x["title"] for x in view.get_workspaces()], ["Superspace 1"]
        )
        # They become visible expanding the superspace tile
        view.request = self.request.clone()
        view.request.form["in_superspace"] = superspace_1.UID()
        self.assertListEqual(
            [x["title"] for x in view.get_workspaces()],
            ["Demo subspace 1", "Sub superspace 1"],
        )
        # but not for the other users
        with api.env.adopt_user("demo"):
            view.request = self.request.clone()
            view.request.form["in_superspace"] = superspace_1.UID()
            self.assertListEqual(
                [x["title"] for x in view.get_workspaces()], ["Demo subspace 1"]
            )

        # Filtering by workspace type is superspace agnostic
        view.request = self.request.clone()
        view.request.form["workspace_type"] = "ploneintranet.workspace.workspacefolder"
        self.assertListEqual(
            [x["title"] for x in view.get_workspaces()], ["Demo subspace 1"]
        )
