"""MIME type handling for ZeptoMail attachments."""

from __future__ import annotations

from zeptomail.exceptions import MimeTypeError

# Extensions blocked by ZeptoMail
UNSUPPORTED_ATTACHMENT_FORMATS: tuple[str, ...] = (
    "ade", "adp", "bat", "chm", "cmd", "com", "cpl", "exe", "hta",
    "ins", "isp", "js", "jse", "lib", "lnk", "mde", "msc", "msp",
    "mst", "pif", "scr", "sct", "shb", "sys", "vb", "vbe", "vbs",
    "vxd", "wsc", "wsf", "wsh", "app", "asp", "bas", "cer", "cnt",
    "crt", "csh", "der", "fxp", "gadget", "hlp", "hpj", "inf", "ksh",
    "mad", "maf", "mag", "mam", "maq", "mar", "mas", "mat", "mau",
    "mav", "maw", "mda", "mdb", "mdt", "mdw", "mdz", "msh", "msh1",
    "msh2", "msh1xml", "msh2xml", "msi", "msp", "ops", "osd", "pcd",
    "plg", "prf", "prg", "pst", "reg", "scf", "shs", "ps1", "ps1xml",
    "ps2", "ps2xml", "psc1", "psc2", "tmp", "url", "vbp", "vsmacros",
    "vsw", "ws", "xnk",
)


class MimeType:
    """Represents a MIME type (e.g. ``application/pdf``).

    Parameters:
        type_: The primary type (e.g. ``application``, ``image``, ``text``).
        subtype: The subtype / extension (e.g. ``pdf``, ``png``, ``plain``).

    Examples::

        >>> mt = MimeType("application", "pdf")
        >>> str(mt)
        'application/pdf'
        >>> mt.is_valid()
        True
    """

    def __init__(self, type_: str = "", subtype: str = "") -> None:
        self.type_ = type_
        self.subtype = subtype

    # ------ helpers ------

    def is_valid(self) -> bool:
        """Return ``True`` if the subtype is not in the blocked list."""
        return self.subtype not in UNSUPPORTED_ATTACHMENT_FORMATS

    def validate(self) -> MimeType:
        """Return *self* if valid, otherwise raise :class:`MimeTypeError`."""
        if not self.is_valid():
            raise MimeTypeError(f"Unsupported MIME type: {self}")
        return self

    @property
    def value(self) -> str:
        """Return the MIME type string used in API payloads (e.g. ``application/pdf``)."""
        return f"{self.type_}/{self.subtype}"

    # ------ class methods ------

    @classmethod
    def from_string(cls, mime_string: str) -> MimeType:
        """Parse a MIME type string like ``application/pdf``.

        Raises:
            ValueError: If the string does not contain exactly one ``/``.
        """
        parts = mime_string.strip().split("/", 1)
        if len(parts) != 2:
            raise ValueError(f"Invalid MIME type string: {mime_string!r}")
        return cls(type_=parts[0], subtype=parts[1])

    # ------ dunder methods ------

    def __str__(self) -> str:
        return self.value

    def __repr__(self) -> str:
        return f"MimeType(type_={self.type_!r}, subtype={self.subtype!r})"

    def __bool__(self) -> bool:
        return bool(self.type_ and self.subtype)

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, MimeType):
            return NotImplemented
        return self.type_ == other.type_ and self.subtype == other.subtype

    def __hash__(self) -> int:
        return hash((self.type_, self.subtype))
