from __future__ import annotations

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

from attrs import define as _attrs_define
from attrs import field as _attrs_field

from ..types import UNSET, Unset

if TYPE_CHECKING:
    from ..models.shopping_list import ShoppingList
    from ..models.supermarket_category import SupermarketCategory


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


@_attrs_define
class FoodShopping:
    """
    Attributes:
        name (str):
        supermarket_category (SupermarketCategory): 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.
        shopping_lists (list[ShoppingList]):
        id (int | Unset):
        plural_name (None | str | Unset):
    """

    name: str
    supermarket_category: SupermarketCategory
    shopping_lists: list[ShoppingList]
    id: int | Unset = UNSET
    plural_name: None | str | Unset = UNSET
    additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

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

        supermarket_category = self.supermarket_category.to_dict()

        shopping_lists = []
        for shopping_lists_item_data in self.shopping_lists:
            shopping_lists_item = shopping_lists_item_data.to_dict()
            shopping_lists.append(shopping_lists_item)

        id = self.id

        plural_name: None | str | Unset
        if isinstance(self.plural_name, Unset):
            plural_name = UNSET
        else:
            plural_name = self.plural_name

        field_dict: dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update(
            {
                "name": name,
                "supermarket_category": supermarket_category,
                "shopping_lists": shopping_lists,
            }
        )
        if id is not UNSET:
            field_dict["id"] = id
        if plural_name is not UNSET:
            field_dict["plural_name"] = plural_name

        return field_dict

    @classmethod
    def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T:
        from ..models.shopping_list import ShoppingList
        from ..models.supermarket_category import SupermarketCategory

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

        supermarket_category = SupermarketCategory.from_dict(d.pop("supermarket_category"))

        shopping_lists = []
        _shopping_lists = d.pop("shopping_lists")
        for shopping_lists_item_data in _shopping_lists:
            shopping_lists_item = ShoppingList.from_dict(shopping_lists_item_data)

            shopping_lists.append(shopping_lists_item)

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

        def _parse_plural_name(data: object) -> None | str | Unset:
            if data is None:
                return data
            if isinstance(data, Unset):
                return data
            return cast(None | str | Unset, data)

        plural_name = _parse_plural_name(d.pop("plural_name", UNSET))

        food_shopping = cls(
            name=name,
            supermarket_category=supermarket_category,
            shopping_lists=shopping_lists,
            id=id,
            plural_name=plural_name,
        )

        food_shopping.additional_properties = d
        return food_shopping

    @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
