import email.parser
from email.message import EmailMessage
from email.policy import default
from typing import TYPE_CHECKING

from bs4 import BeautifulSoup

if TYPE_CHECKING:
    from email.headerregistry import Address, AddressHeader


CTE_HEADER = "content-transfer-encoding"


def parse(data: str) -> EmailMessage:
    parser = email.parser.Parser(policy=default)
    message: EmailMessage = parser.parsestr(data)
    return message


def parse_body(message: EmailMessage) -> str | None:
    if body := message.get_body(preferencelist=("plain", "html", "related")):
        content_charset = body.get_content_charset()
        cte = body[CTE_HEADER]
        body_payload: bytes = body.get_payload(decode=True)
        decoded_payload_text: str
        decoded_payload_text = (
            body_payload.decode("unicode-escape")
            if cte == "8bit" and content_charset == "utf-8"
            else body_payload.decode(content_charset)
        )
        if body.get_content_type() == "text/plain":
            text_cleaned = decoded_payload_text.strip()
        elif body.get_content_type() == "text/html":
            soup = BeautifulSoup(decoded_payload_text, "html.parser")
            text_cleaned = soup.get_text().strip()
        else:
            raise Exception("exception")
        return text_cleaned
    return None


def get_from_header(message: EmailMessage) -> str:
    from_: AddressHeader = message["From"]
    from_addresses = from_.addresses
    from_address: Address = from_addresses[0]
    return from_address.addr_spec


def get_to_header(message: EmailMessage) -> list[str]:
    to_: AddressHeader = message["To"]
    return [dest_address.addr_spec for dest_address in to_.addresses]
