"""
outlook_auth/backeds.py
"""

import base64
import logging

from django.core.mail import EmailMessage
from django.core.mail.backends.smtp import EmailBackend

from base.models import EmailLog
from horilla.horilla_middlewares import _thread_locals
from outlook_auth import models
from outlook_auth.views import send_outlook_email

logger = logging.getLogger(__name__)


class OutlookBackend(EmailBackend):
    """
    OutlookBackend
    """

    api: models.AzureApi = None

    def __init__(self, *args, **kwargs):
        request = getattr(_thread_locals, "request", None)
        self.request = request
        company = None
        if request and not request.user.is_anonymous:
            company = request.user.employee_get.get_company()
        api = models.AzureApi.objects.filter(company=company).first()
        if api is None:
            api = models.AzureApi.objects.filter(is_primary=True).first()
        self.api = api

    def send_messages(self, email_messages):
        response = super().send_messages(email_messages)
        for message in email_messages:
            email_log = EmailLog(
                subject=message.subject,
                from_email=self.dynamic_from_email_with_display_name,
                to=message.to,
                body=message.body,
                status="sent" if response else "failed",
            )
            email_log.save()
        return

    @property
    def dynamic_from_email_with_display_name(self):
        if not self.request.user:
            return f"{self.api.outlook_display_name}<{self.api.outlook_email}>"
        employee = self.request.user.employee_get
        full_name = employee.get_full_name()
        return f"{full_name} <{employee.get_email()}>"


actual_init = EmailMessage.__init__


def __init__(
    self: EmailMessage,
    subject="",
    body="",
    from_email=None,
    to=[],
    bcc=[],
    connection=None,
    attachments=None,
    headers=None,
    cc=[],
    reply_to=None,
    *args,
    **kwargs,
):
    """
    custom __init_method to override
    """
    request = getattr(_thread_locals, "request", None)
    self.request = request

    if request:
        try:
            display_email_name = f"{request.user.employee_get.get_full_name()} <{request.user.employee_get.email}>"
            from_email = display_email_name if not from_email else from_email
            reply_to = [display_email_name] if not reply_to else reply_to

        except Exception as e:
            logger.error(e)
    self.subject = subject
    self.body = body
    self.from_email = from_email
    self.to = to
    self.cc = cc
    self.bcc = bcc
    self.attachments = attachments
    self.headers = headers
    self.reply_to = reply_to

    actual_init(
        self,
        subject=subject,
        body=body,
        from_email=from_email,
        to=to,
        bcc=bcc,
        connection=connection,
        attachments=attachments,
        headers=headers,
        cc=cc,
        reply_to=reply_to,
    )

    # Prepare email data for Outlook API


def send_mail(self, *args, **kwargs):
    """
    Sent mail
    """

    self.email_data = {
        "message": {
            "subject": self.subject,
            "body": {
                "contentType": "HTML" if self.content_subtype == "html" else "Text",
                "content": self.body,
            },
            "toRecipients": [
                {"emailAddress": {"address": recipient}} for recipient in self.to
            ],
            "ccRecipients": [
                {"emailAddress": {"address": recipient}} for recipient in self.cc
            ],
            "bccRecipients": [
                {"emailAddress": {"address": recipient}} for recipient in self.bcc
            ],
        },
    }
    if self.request and not self.request.user.is_anonymous:
        reply_to = self.request.user.employee_get.get_email()
        self.email_data["message"]["replyTo"] = []
        self.email_data["message"]["replyTo"].append(
            {"emailAddress": {"address": reply_to}}
        )

    if self.attachments:
        outlook_attachments = []
        for attachment in self.attachments:
            if isinstance(attachment, tuple):
                filename, content, mimetype = attachment
                if hasattr(content, "read"):
                    content = content.read()

                # Encode contentBytes using base64
                if isinstance(content, bytes):
                    content_bytes = base64.b64encode(content).decode("utf-8")
                else:
                    content_bytes = content

                outlook_attachments.append(
                    {
                        "@odata.type": "#microsoft.graph.fileAttachment",
                        "name": filename,
                        "contentType": mimetype,
                        "contentBytes": content_bytes,
                    }
                )
        self.email_data["message"]["attachments"] = outlook_attachments
    send_outlook_email(self.request, self.email_data)


EmailMessage.__init__ = __init__
EmailMessage.send = send_mail
