from __future__ import annotations

import datetime
import json
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 .. import types
from ..types import UNSET, Unset

if TYPE_CHECKING:
    from ..models.keyword import Keyword


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


@_attrs_define
class ImportLog:
    """
    Attributes:
        type_ (str):
        keyword (Keyword): Moves `UniqueValidator`'s from the validation stage to the save stage.
            It solves the problem with nested validation for unique fields on update.

            If you want more details, you can read related issues and articles:
            https://github.com/beda-software/drf-writable-nested/issues/1
            http://www.django-rest-framework.org/api-guide/validators/#updating-nested-serializers

            Example of usage:
            ```
                class Child(models.Model):
                field = models.CharField(unique=True)


            class Parent(models.Model):
                child = models.ForeignKey('Child')


            class ChildSerializer(UniqueFieldsMixin, serializers.ModelSerializer):
                class Meta:
                    model = Child


            class ParentSerializer(NestedUpdateMixin, serializers.ModelSerializer):
                child = ChildSerializer()

                class Meta:
                    model = Parent
            ```

            Note: `UniqueFieldsMixin` must be applied only on the serializer
            which has unique fields.

            Note: When you are using both mixins
            (`UniqueFieldsMixin` and `NestedCreateMixin` or `NestedUpdateMixin`)
            you should put `UniqueFieldsMixin` ahead.
        created_by (int):
        created_at (datetime.datetime):
        id (int | Unset):
        msg (str | Unset):
        running (bool | Unset):
        total_recipes (int | Unset):
        imported_recipes (int | Unset):
    """

    type_: str
    keyword: Keyword
    created_by: int
    created_at: datetime.datetime
    id: int | Unset = UNSET
    msg: str | Unset = UNSET
    running: bool | Unset = UNSET
    total_recipes: int | Unset = UNSET
    imported_recipes: int | Unset = UNSET
    additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

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

        keyword = self.keyword.to_dict()

        created_by = self.created_by

        created_at = self.created_at.isoformat()

        id = self.id

        msg = self.msg

        running = self.running

        total_recipes = self.total_recipes

        imported_recipes = self.imported_recipes

        field_dict: dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update(
            {
                "type": type_,
                "keyword": keyword,
                "created_by": created_by,
                "created_at": created_at,
            }
        )
        if id is not UNSET:
            field_dict["id"] = id
        if msg is not UNSET:
            field_dict["msg"] = msg
        if running is not UNSET:
            field_dict["running"] = running
        if total_recipes is not UNSET:
            field_dict["total_recipes"] = total_recipes
        if imported_recipes is not UNSET:
            field_dict["imported_recipes"] = imported_recipes

        return field_dict

    def to_multipart(self) -> types.RequestFiles:
        files: types.RequestFiles = []

        files.append(("type", (None, str(self.type_).encode(), "text/plain")))

        files.append(("keyword", (None, json.dumps(self.keyword.to_dict()).encode(), "application/json")))

        files.append(("created_by", (None, str(self.created_by).encode(), "text/plain")))

        files.append(("created_at", (None, self.created_at.isoformat().encode(), "text/plain")))

        if not isinstance(self.id, Unset):
            files.append(("id", (None, str(self.id).encode(), "text/plain")))

        if not isinstance(self.msg, Unset):
            files.append(("msg", (None, str(self.msg).encode(), "text/plain")))

        if not isinstance(self.running, Unset):
            files.append(("running", (None, str(self.running).encode(), "text/plain")))

        if not isinstance(self.total_recipes, Unset):
            files.append(("total_recipes", (None, str(self.total_recipes).encode(), "text/plain")))

        if not isinstance(self.imported_recipes, Unset):
            files.append(("imported_recipes", (None, str(self.imported_recipes).encode(), "text/plain")))

        for prop_name, prop in self.additional_properties.items():
            files.append((prop_name, (None, str(prop).encode(), "text/plain")))

        return files

    @classmethod
    def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
        from ..models.keyword import Keyword

        d = dict(src_dict)
        type_ = d.pop("type")

        keyword = Keyword.from_dict(d.pop("keyword"))

        created_by = d.pop("created_by")

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

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

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

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

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

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

        import_log = cls(
            type_=type_,
            keyword=keyword,
            created_by=created_by,
            created_at=created_at,
            id=id,
            msg=msg,
            running=running,
            total_recipes=total_recipes,
            imported_recipes=imported_recipes,
        )

        import_log.additional_properties = d
        return import_log

    @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
