from __future__ import annotations

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

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

from ..types import UNSET, Unset

if TYPE_CHECKING:
    from ..models.document_note import DocumentNote
    from ..models.document_sharing import DocumentSharing
    from ..models.metadata import Metadata
    from ..models.sync_info import SyncInfo
    from ..models.table import Table


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


@_attrs_define
class DocumentUpdateBodyDocDiff:
    """Fields to update

    Attributes:
        name (str | Unset):
        stack (str | Unset): MongoDB ObjectId
        metadata (list[Metadata] | Unset):
        tables (list[Table] | Unset):
        reviewed (bool | Unset):
        archived (bool | Unset):
        urgent (bool | Unset):
        flagged (bool | Unset):
        pinned (bool | Unset):
        assignee (str | Unset): MongoDB ObjectId
        deadline (datetime.datetime | Unset):
        sharing (DocumentSharing | Unset):
        notes (list[DocumentNote] | Unset):
        sync (list[SyncInfo] | Unset):
        index_statement (bool | Unset): Create TPA statement from metadata
    """

    name: str | Unset = UNSET
    stack: str | Unset = UNSET
    metadata: list[Metadata] | Unset = UNSET
    tables: list[Table] | Unset = UNSET
    reviewed: bool | Unset = UNSET
    archived: bool | Unset = UNSET
    urgent: bool | Unset = UNSET
    flagged: bool | Unset = UNSET
    pinned: bool | Unset = UNSET
    assignee: str | Unset = UNSET
    deadline: datetime.datetime | Unset = UNSET
    sharing: DocumentSharing | Unset = UNSET
    notes: list[DocumentNote] | Unset = UNSET
    sync: list[SyncInfo] | Unset = UNSET
    index_statement: bool | Unset = UNSET
    additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

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

        stack = self.stack

        metadata: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.metadata, Unset):
            metadata = []
            for metadata_item_data in self.metadata:
                metadata_item = metadata_item_data.to_dict()
                metadata.append(metadata_item)

        tables: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.tables, Unset):
            tables = []
            for tables_item_data in self.tables:
                tables_item = tables_item_data.to_dict()
                tables.append(tables_item)

        reviewed = self.reviewed

        archived = self.archived

        urgent = self.urgent

        flagged = self.flagged

        pinned = self.pinned

        assignee = self.assignee

        deadline: str | Unset = UNSET
        if not isinstance(self.deadline, Unset):
            deadline = self.deadline.isoformat()

        sharing: dict[str, Any] | Unset = UNSET
        if not isinstance(self.sharing, Unset):
            sharing = self.sharing.to_dict()

        notes: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.notes, Unset):
            notes = []
            for notes_item_data in self.notes:
                notes_item = notes_item_data.to_dict()
                notes.append(notes_item)

        sync: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.sync, Unset):
            sync = []
            for sync_item_data in self.sync:
                sync_item = sync_item_data.to_dict()
                sync.append(sync_item)

        index_statement = self.index_statement

        field_dict: dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update({})
        if name is not UNSET:
            field_dict["name"] = name
        if stack is not UNSET:
            field_dict["stack"] = stack
        if metadata is not UNSET:
            field_dict["metadata"] = metadata
        if tables is not UNSET:
            field_dict["tables"] = tables
        if reviewed is not UNSET:
            field_dict["reviewed"] = reviewed
        if archived is not UNSET:
            field_dict["archived"] = archived
        if urgent is not UNSET:
            field_dict["urgent"] = urgent
        if flagged is not UNSET:
            field_dict["flagged"] = flagged
        if pinned is not UNSET:
            field_dict["pinned"] = pinned
        if assignee is not UNSET:
            field_dict["assignee"] = assignee
        if deadline is not UNSET:
            field_dict["deadline"] = deadline
        if sharing is not UNSET:
            field_dict["sharing"] = sharing
        if notes is not UNSET:
            field_dict["notes"] = notes
        if sync is not UNSET:
            field_dict["sync"] = sync
        if index_statement is not UNSET:
            field_dict["indexStatement"] = index_statement

        return field_dict

    @classmethod
    def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
        from ..models.document_note import DocumentNote
        from ..models.document_sharing import DocumentSharing
        from ..models.metadata import Metadata
        from ..models.sync_info import SyncInfo
        from ..models.table import Table

        d = dict(src_dict)
        name = d.pop("name", UNSET)

        stack = d.pop("stack", UNSET)

        _metadata = d.pop("metadata", UNSET)
        metadata: list[Metadata] | Unset = UNSET
        if _metadata is not UNSET:
            metadata = []
            for metadata_item_data in _metadata:
                metadata_item = Metadata.from_dict(metadata_item_data)

                metadata.append(metadata_item)

        _tables = d.pop("tables", UNSET)
        tables: list[Table] | Unset = UNSET
        if _tables is not UNSET:
            tables = []
            for tables_item_data in _tables:
                tables_item = Table.from_dict(tables_item_data)

                tables.append(tables_item)

        reviewed = d.pop("reviewed", UNSET)

        archived = d.pop("archived", UNSET)

        urgent = d.pop("urgent", UNSET)

        flagged = d.pop("flagged", UNSET)

        pinned = d.pop("pinned", UNSET)

        assignee = d.pop("assignee", UNSET)

        _deadline = d.pop("deadline", UNSET)
        deadline: datetime.datetime | Unset
        if isinstance(_deadline, Unset):
            deadline = UNSET
        else:
            deadline = isoparse(_deadline)

        _sharing = d.pop("sharing", UNSET)
        sharing: DocumentSharing | Unset
        if isinstance(_sharing, Unset):
            sharing = UNSET
        else:
            sharing = DocumentSharing.from_dict(_sharing)

        _notes = d.pop("notes", UNSET)
        notes: list[DocumentNote] | Unset = UNSET
        if _notes is not UNSET:
            notes = []
            for notes_item_data in _notes:
                notes_item = DocumentNote.from_dict(notes_item_data)

                notes.append(notes_item)

        _sync = d.pop("sync", UNSET)
        sync: list[SyncInfo] | Unset = UNSET
        if _sync is not UNSET:
            sync = []
            for sync_item_data in _sync:
                sync_item = SyncInfo.from_dict(sync_item_data)

                sync.append(sync_item)

        index_statement = d.pop("indexStatement", UNSET)

        document_update_body_doc_diff = cls(
            name=name,
            stack=stack,
            metadata=metadata,
            tables=tables,
            reviewed=reviewed,
            archived=archived,
            urgent=urgent,
            flagged=flagged,
            pinned=pinned,
            assignee=assignee,
            deadline=deadline,
            sharing=sharing,
            notes=notes,
            sync=sync,
            index_statement=index_statement,
        )

        document_update_body_doc_diff.additional_properties = d
        return document_update_body_doc_diff

    @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
