from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from typing import Optional, List

import aiosmtplib
import anyio

from starlette_web.common.email.base_sender import BaseEmailSender
from starlette_web.common.http.exceptions import NotSupportedError
from starlette_web.common.utils import get_available_options


class SMTPEmailSender(BaseEmailSender):
    SEND_MAX_TIME = 30

    async def send_email(
        self,
        subject: str,
        html_content: str,
        recipients_list: List[str],
        from_email: Optional[str] = None,
    ):
        message = MIMEMultipart("alternative")
        message["Subject"] = subject
        _from = from_email
        if _from is None:
            _from = self.options.get("from")
        if _from is None:
            raise NotSupportedError(
                details="Cannot send email without setting FROM field."
            )
        message["From"] = _from

        html_part = MIMEText(html_content, "html")
        message.attach(html_part)

        _recipients = recipients_list.copy()
        while _recipients:
            available_args = get_available_options(aiosmtplib.send)
            options = dict(
                message=message,
                sender=_from,
                recipients=_recipients[:self.MAX_BULK_SIZE],
                **self.options,
            )

            with anyio.move_on_after(self.SEND_MAX_TIME):
                await aiosmtplib.send(**{
                    key: value
                    for key, value in options.items()
                    if key in available_args
                })

            del _recipients[:self.MAX_BULK_SIZE]
