from __future__ import annotations

import datetime
from collections.abc import Mapping
from typing import TYPE_CHECKING, Any, TypeVar, cast
from uuid import UUID

from attrs import define as _attrs_define
from attrs import field as _attrs_field
from dateutil.parser import isoparse

if TYPE_CHECKING:
    from ..models.message_hallpass_verification import MessageHallpassVerification
    from ..models.message_local_verification import MessageLocalVerification


T = TypeVar("T", bound="Message")


@_attrs_define
class Message:
    """
    Attributes:
        id (UUID):
        signer_profile_id (None | UUID):
        delegation_id (None | UUID):
        principal_username (str):
        author_label (str):
        body (str):
        signer_did (str):
        verification_method (str):
        key_fingerprint (str):
        local_verification (MessageLocalVerification):
        hallpass_verification (MessageHallpassVerification):
        hosted_verification_path (str):
        inserted_at (datetime.datetime):
    """

    id: UUID
    signer_profile_id: None | UUID
    delegation_id: None | UUID
    principal_username: str
    author_label: str
    body: str
    signer_did: str
    verification_method: str
    key_fingerprint: str
    local_verification: MessageLocalVerification
    hallpass_verification: MessageHallpassVerification
    hosted_verification_path: str
    inserted_at: datetime.datetime
    additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

    def to_dict(self) -> dict[str, Any]:
        id = str(self.id)

        signer_profile_id: None | str
        if isinstance(self.signer_profile_id, UUID):
            signer_profile_id = str(self.signer_profile_id)
        else:
            signer_profile_id = self.signer_profile_id

        delegation_id: None | str
        if isinstance(self.delegation_id, UUID):
            delegation_id = str(self.delegation_id)
        else:
            delegation_id = self.delegation_id

        principal_username = self.principal_username

        author_label = self.author_label

        body = self.body

        signer_did = self.signer_did

        verification_method = self.verification_method

        key_fingerprint = self.key_fingerprint

        local_verification = self.local_verification.to_dict()

        hallpass_verification = self.hallpass_verification.to_dict()

        hosted_verification_path = self.hosted_verification_path

        inserted_at = self.inserted_at.isoformat()

        field_dict: dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update(
            {
                "id": id,
                "signer_profile_id": signer_profile_id,
                "delegation_id": delegation_id,
                "principal_username": principal_username,
                "author_label": author_label,
                "body": body,
                "signer_did": signer_did,
                "verification_method": verification_method,
                "key_fingerprint": key_fingerprint,
                "local_verification": local_verification,
                "hallpass_verification": hallpass_verification,
                "hosted_verification_path": hosted_verification_path,
                "inserted_at": inserted_at,
            }
        )

        return field_dict

    @classmethod
    def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
        from ..models.message_hallpass_verification import MessageHallpassVerification
        from ..models.message_local_verification import MessageLocalVerification

        d = dict(src_dict)
        id = UUID(d.pop("id"))

        def _parse_signer_profile_id(data: object) -> None | UUID:
            if data is None:
                return data
            try:
                if not isinstance(data, str):
                    raise TypeError()
                signer_profile_id_type_0 = UUID(data)

                return signer_profile_id_type_0
            except (TypeError, ValueError, AttributeError, KeyError):
                pass
            return cast(None | UUID, data)

        signer_profile_id = _parse_signer_profile_id(d.pop("signer_profile_id"))

        def _parse_delegation_id(data: object) -> None | UUID:
            if data is None:
                return data
            try:
                if not isinstance(data, str):
                    raise TypeError()
                delegation_id_type_0 = UUID(data)

                return delegation_id_type_0
            except (TypeError, ValueError, AttributeError, KeyError):
                pass
            return cast(None | UUID, data)

        delegation_id = _parse_delegation_id(d.pop("delegation_id"))

        principal_username = d.pop("principal_username")

        author_label = d.pop("author_label")

        body = d.pop("body")

        signer_did = d.pop("signer_did")

        verification_method = d.pop("verification_method")

        key_fingerprint = d.pop("key_fingerprint")

        local_verification = MessageLocalVerification.from_dict(d.pop("local_verification"))

        hallpass_verification = MessageHallpassVerification.from_dict(d.pop("hallpass_verification"))

        hosted_verification_path = d.pop("hosted_verification_path")

        inserted_at = isoparse(d.pop("inserted_at"))

        message = cls(
            id=id,
            signer_profile_id=signer_profile_id,
            delegation_id=delegation_id,
            principal_username=principal_username,
            author_label=author_label,
            body=body,
            signer_did=signer_did,
            verification_method=verification_method,
            key_fingerprint=key_fingerprint,
            local_verification=local_verification,
            hallpass_verification=hallpass_verification,
            hosted_verification_path=hosted_verification_path,
            inserted_at=inserted_at,
        )

        message.additional_properties = d
        return message

    @property
    def additional_keys(self) -> list[str]:
        return list(self.additional_properties.keys())

    def __getitem__(self, key: str) -> Any:
        return self.additional_properties[key]

    def __setitem__(self, key: str, value: Any) -> None:
        self.additional_properties[key] = value

    def __delitem__(self, key: str) -> None:
        del self.additional_properties[key]

    def __contains__(self, key: str) -> bool:
        return key in self.additional_properties
