#  Copyright (C) 2021
#  ABM, Moscow
#
#  UNPUBLISHED PROPRIETARY MATERIAL.
#  ALL RIGHTS RESERVED.
#
#  Authors: Vasya Svintsov <v.svintsov@techokert.ru>

from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import formataddr
from typing import Union, Optional, List

from bs4 import BeautifulSoup
from http_tools.attached_file import AttachedFile
from http_tools.charset import Charset


def generate_message(source_email_account: str,
                     to_recipients: Union[str, List[str]],
                     subject: str,
                     body: str,
                     *,
                     source_email_account_name: Optional[str] = None,
                     attachments: Optional[List[AttachedFile]] = None,
                     cc_recipients: Optional[Union[str, List[str]]] = None,
                     bcc_recipients: Optional[Union[str, List[str]]] = None,
                     message_id: Optional[str] = None,
                     in_reply_to: Optional[str] = None,
                     references: Optional[str] = None
                     ) -> MIMEMultipart:
    """
    Creates a multipart/* type message.

    :param source_email_account: The source email account.
    :param to_recipients: The destination email accounts.
    :param subject: The subject of the email.
    :param body: The plain text/HTML version of the body of the email.
    :param source_email_account_name: The name of the source email account.
    :param attachments: The attachment part of the body of the email.
    :param cc_recipients: The list of recipients on the 'CC'.
    :param bcc_recipients: The list of recipients on the 'BCC'.
    :param message_id: string a single unique message identifier RFC 2822.
    :param in_reply_to: string field contain one or more unique message identifiers, optionally separated by CFWS RFC 2822.
    :param references: same as in_reply_to
    """

    if source_email_account_name is not None:
        source_email_account = formataddr((source_email_account_name, source_email_account), Charset.UTF8)

    message = MIMEMultipart('mixed')
    message['From'] = source_email_account
    message['Subject'] = subject

    to_recipients = [to_recipients] if not isinstance(to_recipients, list) else to_recipients
    message['To'] = ", ".join(to_recipients)
    if cc_recipients is not None:
        cc_recipients = [cc_recipients] if not isinstance(cc_recipients, list) else cc_recipients
        message['Cc'] = ", ".join(cc_recipients)
    if bcc_recipients is not None:
        bcc_recipients = [bcc_recipients] if not isinstance(bcc_recipients, list) else bcc_recipients
        message['Bcc'] = ", ".join(bcc_recipients)
    if message_id is not None:
        message['Message-ID'] = message_id
    if in_reply_to is not None:
        message['In-Reply-To'] = in_reply_to
    if references is not None:
        message['References'] = references

    message_body = MIMEMultipart('alternative')
    message_body.attach(MIMEText(BeautifulSoup(body, "html.parser").get_text(), 'plain', Charset.UTF8))
    message_body.attach(MIMEText(body, 'html', Charset.UTF8))
    message.attach(message_body)

    for attachment in attachments if attachments is not None else []:
        part = MIMEApplication(attachment.content)
        part.add_header("Content-Disposition", "attachment", filename=(Charset.UTF8, '', attachment.filename))
        message.attach(part)

    return message
