# pylint: disable=abstract-method
import mimetypes
from os.path import basename

from django.conf import settings
from django.core.mail import EmailMessage, EmailMultiAlternatives

from ocyan.main.loading import get_baseclass
from ocyan.plugin.oscar.info import OSCAR_NEEDS_OXYAN

if OSCAR_NEEDS_OXYAN:
    OscarDispatcher = get_baseclass(
        "communication.utils",
        "Dispatcher",
        "ocyan.plugin.oscar_communications.customer_extension",
    )
else:
    OscarDispatcher = get_baseclass(
        "customer.utils",
        "Dispatcher",
        "ocyan.plugin.oscar_communications.customer_extension",
    )


class Dispatcher(OscarDispatcher):
    def __init__(self, logger=None, mail_connection=None):
        super().__init__(logger=logger, mail_connection=mail_connection)
        self.bcc_admins = False

    def send_email_messages(self, recipient, messages):
        """
        Send email to recipient, HTML attachment optional.
        """
        if hasattr(settings, "OSCAR_FROM_EMAIL"):
            from_email = settings.OSCAR_FROM_EMAIL
        else:
            from_email = None

        # Determine whether we are sending a HTML version too
        if messages["html"]:
            email = EmailMultiAlternatives(
                messages["subject"],
                messages["body"],
                from_email=from_email,
                to=[recipient],
            )
            email.attach_alternative(messages["html"], "text/html")
        else:
            email = EmailMessage(
                messages["subject"],
                messages["body"],
                from_email=from_email,
                to=[recipient],
            )
        if "attachments" in messages:
            for attachment in messages["attachments"]:
                content_type, _ = mimetypes.guess_type(attachment.name)
                email.attach(basename(attachment.name), attachment.read(), content_type)

        if self.bcc_admins:
            email.bcc = list(settings.DEFAULT_TO_EMAIL)

        self.logger.info("Sending email to %s", email.recipients())

        if self.mail_connection:
            self.mail_connection.send_messages([email])
        else:
            email.send()

        return email

    def dispatch_order_messages(self, order, messages, event_type=None, **kwargs):
        """
        Dispatch order-related messages to the customer.
        """
        has_billing_address = order.billing_address and order.billing_address.email

        if order.is_anonymous:
            email = kwargs.get("email_address", order.guest_email)
            if has_billing_address and email != order.billing_address.email:
                messages = self.send_billing_email(order, messages)
            dispatched_messages = self.dispatch_anonymous_messages(email, messages)
        else:
            if has_billing_address and order.user.email != order.billing_address.email:
                messages = self.send_billing_email(order, messages)
            dispatched_messages = self.dispatch_user_messages(order.user, messages)

        self.create_communication_event(order, event_type, dispatched_messages)

    def send_billing_email(self, order, messages):
        self.dispatch_direct_messages(order.billing_address.email, messages)
        # We pop out the attachments if there is a billing email because we don't want to send the invoice to the user email.
        messages.pop("attachments", None)
        return messages


class BccDispatcher(Dispatcher):
    def __init__(self, bcc_admins=False, logger=None, mail_connection=None):
        super(BccDispatcher, self).__init__(
            logger=logger, mail_connection=mail_connection
        )
        self.bcc_admins = bcc_admins
