from email import message_from_bytes
from plone.app.testing import SITE_OWNER_NAME
from plone.app.testing import SITE_OWNER_PASSWORD
from plone.testing.zope import Browser
from ploneintranet.invitations.testing import FunctionalTestCase
from zope.component import getMultiAdapter


class TestInviteUser(FunctionalTestCase):
    def setUp(self):
        self.app = self.layer["app"]
        self.portal = self.layer["portal"]
        self.request = self.layer["request"]
        self.mailhost = self.portal.MailHost

        self.browser = Browser(self.app)
        self.browser.handleErrors = False

        # Commit so that the test browser sees these changes
        import transaction

        transaction.commit()

    def test_invite_user(self):
        email = "test@test.com"
        view = getMultiAdapter(
            (self.portal, self.request), name="ploneintranet-invitations-invite-user"
        )
        token_id, token_url = view.invite_user(email)

        self.assertEqual(len(self.mailhost.messages), 1)
        msg = message_from_bytes(self.mailhost.messages[0])
        self.assertEqual(msg["To"], email)
        self.assertIn(token_url, msg.get_payload())
        self.mailhost.reset()

        # Commit so that the test browser sees these changes
        import transaction

        transaction.commit()

        self.browser.open(token_url)

        # We should now be authenticated
        self.assertIn(
            "userrole-authenticated",
            self.browser.contents,
            "User was not authenticated after accepting token",
        )
        self.assertIn(
            email,
            self.browser.contents,
            "Incorrect user authenticated after accepting token",
        )

        # Logout
        self.browser.open(f"{self.portal.absolute_url()}/logout")

        # A token is valid only one time.
        self.browser.open(token_url)

        # We should NOT be authenticated
        self.assertIn(
            "userrole-anonymous", self.browser.contents, "User was authenticated"
        )

        # Try an invalid token
        self.browser.open(
            f"{self.portal.absolute_url()}/@@accept-token/thisisnotatoken"
        )
        self.assertNotIn(
            "userrole-authenticated",
            self.browser.contents,
            "Invalid token should not allow access",
        )

        # No token
        with self.assertRaises(KeyError):
            self.browser.open(f"{self.portal.absolute_url()}/@@accept-token")

    def test_invite_user_form(self):
        email = "test@test.com"

        self.browser.open(self.portal.absolute_url() + "/login_form")
        self.browser.getControl(name="__ac_name").value = SITE_OWNER_NAME
        self.browser.getControl(name="__ac_password").value = SITE_OWNER_PASSWORD
        self.browser.getControl(name="buttons.login").click()
        self.browser.open(
            "%s/@@ploneintranet-invitations-invite-user" % self.portal.absolute_url()
        )
        self.browser.getControl(name="email").value = email
        self.browser.getControl(name="send").click()

        self.assertEqual(len(self.mailhost.messages), 1)
        msg = message_from_bytes(self.mailhost.messages[0])
        self.assertEqual(msg["To"], email)
