from collective.workspace.interfaces import IWorkspace
from plone import api
from plone.app.z3cform.widget import AjaxSelectFieldWidget
from plone.autoform import directives
from plone.autoform.form import AutoExtensibleForm
from plone.supermodel import model
from ploneintranet.core import _
from ploneintranet.invitations.interfaces import ITokenUtility
from ploneintranet.workspace.utils import get_storage
from z3c.form import button
from z3c.form import form
from z3c.form.interfaces import WidgetActionExecutionError
from zope import schema
from zope.component import getUtility
from zope.interface import Invalid


def user_has_email(userid):
    """make sure, that given user has an email associated"""
    user = api.user.get(userid=userid)
    if not user.getProperty("email"):
        msg = _("This user doesn't have an email associated " "with their account.")
        raise Invalid(msg)

    return True


class IInviteForm(model.Schema):
    """
    invite form schema
    """

    directives.widget(
        "user", AjaxSelectFieldWidget, vocabulary="plone.app.vocabularies.Users"
    )
    user = schema.TextLine(title=_("User"), constraint=user_has_email)
    message = schema.Text(title=_("Message"), default="", required=False)


class InviteForm(AutoExtensibleForm, form.Form):
    """
    handle invite form submission
    """

    schema = IInviteForm
    ignoreContext = True

    label = _("invititations", default="Invitations")

    @button.buttonAndHandler("Ok")
    def handleApply(self, action):
        data = self.extractData()[0]
        given_userid = data.get("user", "").strip()
        given_message = data.get("message", "") or ""
        given_message = given_message.strip()
        workspace_title = self.context.title
        if not given_userid:
            return

        ws = IWorkspace(self.context)
        for name in ws.members:
            member = api.user.get(userid=name)
            if member is not None:
                if member.getId() == given_userid:
                    raise WidgetActionExecutionError(
                        "user", Invalid("User is already a member of this workspace")
                    )

        user = api.user.get(userid=given_userid)
        email = user.getProperty("email")

        token_util = getUtility(ITokenUtility)
        token_id, token_url = token_util.generate_new_token(
            redirect_path=f"resolveuid/{ws.context.UID()}"
        )
        storage = get_storage()
        storage[token_id] = (ws.context.UID(), given_userid)

        current_user = api.user.get_current()
        inviter = current_user.getProperty("fullname", None)
        if not inviter:
            inviter = current_user.getId()
        inviter = inviter

        msg_header = "You have been invited to join {} by {}".format(
            workspace_title,
            inviter,
        )

        if given_message:
            optional = "Here is the message from %s\n\n" % inviter
            optional = f"{optional}{given_message}\n\n"
            given_message = optional

        msg_footer = """
The following is a unique URL tied to your email address ({email}).

Following the link will make you a member of the {workspace} workspace
automatically.

{token_url}

""".format(email=email, workspace=workspace_title, token_url=token_url)

        message = "{header}\n\n{optional}{footer}".format(
            header=msg_header, optional=given_message, footer=msg_footer
        )

        subject = 'You are invited to join "%s"' % workspace_title
        api.portal.send_email(
            recipient=email,
            subject=subject,
            body=message,
        )
        api.portal.show_message("Invitation sent to %s" % email, self.request)
