from plone import api
from plone.api.exc import InvalidParameterError
from ploneintranet import api as pi_api
from ploneintranet.testing import temporary_registry_record
from ploneintranet.userprofile.tests.base import BaseTestCase
from zExceptions import Unauthorized


class TestUserProfilePermissions(BaseTestCase):
    def setUp(self):
        super().setUp()
        self.login_as_portal_owner()
        api.user.create(email="bob@hotmail.com", username="bob")
        self.logout()

    def test_add_container_permissions(self):
        with api.env.adopt_user("bob"):
            with self.assertRaises(Unauthorized):
                api.content.create(
                    title="Profiles",
                    type="ploneintranet.userprofile.userprofilecontainer",
                    container=self.portal,
                )
            with api.env.adopt_roles(["Manager"]):
                api.content.create(
                    title="Profiles",
                    type="ploneintranet.userprofile.userprofilecontainer",
                    container=self.portal,
                )

    def test_add_user_permissions(self):
        with api.env.adopt_user("bob"):
            with self.assertRaises(Unauthorized):
                api.content.create(
                    id="another-user",
                    username="another-user",
                    type="ploneintranet.userprofile.userprofile",
                    container=self.profiles,
                )
            with api.env.adopt_roles(["Site Administrator"]):
                api.content.create(
                    id="another-user",
                    username="another-user",
                    type="ploneintranet.userprofile.userprofile",
                    container=self.profiles,
                )

    def test_approve_user_permissions(self):
        with api.env.adopt_user("admin"):
            profile = api.content.create(
                id="another-user",
                username="another-user",
                type="ploneintranet.userprofile.userprofile",
                container=self.profiles,
            )
        with api.env.adopt_user("bob"):
            with api.env.adopt_roles(["Reviewer"]):
                with self.assertRaises(InvalidParameterError):
                    api.content.transition(profile, "approve")
            with api.env.adopt_roles(["Site Administrator"]):
                api.content.transition(profile, "approve")


class TestUserProfileTransitions(BaseTestCase):
    def setUp(self):
        super().setUp()
        self.login_as_portal_owner()
        self.profile_bob = pi_api.userprofile.create(
            email="bob@hotmail.com", username="bob", approve=True
        )
        self.profile_jane = pi_api.userprofile.create(
            email="jane@hotmail.com", username="jane", approve=False
        )

    def test_approve_into_intranet(self):
        intranet = pi_api.workgroup.get("intranet")
        self.assertEqual(api.content.get_state(self.profile_bob), "enabled")
        self.assertIn("bob", intranet.members)
        self.assertEqual(api.content.get_state(self.profile_jane), "pending")
        self.assertNotIn("jane", intranet.members)
        api.content.transition(self.profile_jane, "approve")
        self.assertEqual(api.content.get_state(self.profile_jane), "enabled")
        self.assertIn("jane", intranet.members)

    def test_disable_enable_changes_email(self):
        api.content.transition(self.profile_bob, "disable")
        self.assertEqual(self.profile_bob.email, "DISABLED-bob@hotmail.com")

        api.content.transition(self.profile_bob, "enable")
        self.assertEqual(self.profile_bob.email, "bob@hotmail.com")

        self.profile_bob.email = "DISABLED-FOO-bob@hotmail.com"
        api.content.transition(self.profile_bob, "disable")
        self.assertEqual(self.profile_bob.email, "DISABLED-FOO-bob@hotmail.com")

        self.profile_bob.email = "FOO-bob@hotmail.com"
        api.content.transition(self.profile_bob, "enable")
        self.assertEqual(self.profile_bob.email, "FOO-bob@hotmail.com")

    def get_indexes_for(self, email):
        membrane_tool = api.portal.get_tool("membrane_tool")
        brains = membrane_tool.searchResults()
        index_data = [
            membrane_tool.getIndexDataForRID(brain.getRID()) for brain in brains
        ]
        index_by_email = {data["email"]: data for data in index_data}
        found = index_by_email[email]
        return {
            "getUserName": found["getUserName"],
            "exact_getUserName": found["exact_getUserName"],
        }

    @temporary_registry_record(
        "dexterity.membrane.behavior.settings.IDexterityMembraneSettings.use_email_as_username",  # noqa
        True,
    )
    def test_disable_enable_reindexes_getUserName(self):
        # switching to email_as_username after creating the users leaves the
        # membrane indexs in an inconsistent state
        self.assertDictEqual(
            self.get_indexes_for("bob@hotmail.com"),
            {"getUserName": ["bob"], "exact_getUserName": "bob"},
        )
        self.assertDictEqual(
            self.get_indexes_for("jane@hotmail.com"),
            {
                "getUserName": ["jane", "hotmail", "com"],
                "exact_getUserName": "jane@hotmail.com",
            },
        )

        # reindex both users and recheck
        membrane_tool = api.portal.get_tool("membrane_tool")
        membrane_tool.reindexObject(self.profile_bob)
        membrane_tool.reindexObject(self.profile_jane)
        self.assertDictEqual(
            self.get_indexes_for("bob@hotmail.com"),
            {
                "getUserName": ["bob", "hotmail", "com"],
                "exact_getUserName": "bob@hotmail.com",
            },
        )
        self.assertDictEqual(
            self.get_indexes_for("jane@hotmail.com"),
            {
                "getUserName": ["jane", "hotmail", "com"],
                "exact_getUserName": "jane@hotmail.com",
            },
        )

        # disabling a user should reflect in the indexes
        api.content.transition(self.profile_bob, "disable")
        self.assertEqual(self.profile_bob.email, "DISABLED-bob@hotmail.com")
        self.assertDictEqual(
            self.get_indexes_for("DISABLED-bob@hotmail.com"),
            {
                "getUserName": ["disabled", "bob", "hotmail", "com"],
                "exact_getUserName": "DISABLED-bob@hotmail.com",
            },
        )

        # enabling a user should reflect in the indexes
        api.content.transition(self.profile_bob, "enable")
        self.assertDictEqual(
            self.get_indexes_for("bob@hotmail.com"),
            {
                "getUserName": ["bob", "hotmail", "com"],
                "exact_getUserName": "bob@hotmail.com",
            },
        )
