from __future__ import annotations

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

if TYPE_CHECKING:
    from ..models.ingredient import Ingredient
    from ..models.user_file_view import UserFileView


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


@_attrs_define
class PatchedStep:
    """Adds nested create feature

    Attributes:
        id (int | Unset):
        name (str | Unset):
        instruction (str | Unset):
        ingredients (list[Ingredient] | Unset):
        instructions_markdown (str | Unset):
        time (int | Unset):
        order (int | Unset):
        show_as_header (bool | Unset):
        file (None | Unset | UserFileView):
        step_recipe (int | None | Unset):
        step_recipe_data (Any | Unset):
        numrecipe (int | Unset):
        show_ingredients_table (bool | Unset):
    """

    id: int | Unset = UNSET
    name: str | Unset = UNSET
    instruction: str | Unset = UNSET
    ingredients: list[Ingredient] | Unset = UNSET
    instructions_markdown: str | Unset = UNSET
    time: int | Unset = UNSET
    order: int | Unset = UNSET
    show_as_header: bool | Unset = UNSET
    file: None | Unset | UserFileView = UNSET
    step_recipe: int | None | Unset = UNSET
    step_recipe_data: Any | Unset = UNSET
    numrecipe: int | Unset = UNSET
    show_ingredients_table: bool | Unset = UNSET
    additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

    def to_dict(self) -> dict[str, Any]:
        from ..models.user_file_view import UserFileView

        id = self.id

        name = self.name

        instruction = self.instruction

        ingredients: list[dict[str, Any]] | Unset = UNSET
        if not isinstance(self.ingredients, Unset):
            ingredients = []
            for ingredients_item_data in self.ingredients:
                ingredients_item = ingredients_item_data.to_dict()
                ingredients.append(ingredients_item)

        instructions_markdown = self.instructions_markdown

        time = self.time

        order = self.order

        show_as_header = self.show_as_header

        file: dict[str, Any] | None | Unset
        if isinstance(self.file, Unset):
            file = UNSET
        elif isinstance(self.file, UserFileView):
            file = self.file.to_dict()
        else:
            file = self.file

        step_recipe: int | None | Unset
        if isinstance(self.step_recipe, Unset):
            step_recipe = UNSET
        else:
            step_recipe = self.step_recipe

        step_recipe_data = self.step_recipe_data

        numrecipe = self.numrecipe

        show_ingredients_table = self.show_ingredients_table

        field_dict: dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update({})
        if id is not UNSET:
            field_dict["id"] = id
        if name is not UNSET:
            field_dict["name"] = name
        if instruction is not UNSET:
            field_dict["instruction"] = instruction
        if ingredients is not UNSET:
            field_dict["ingredients"] = ingredients
        if instructions_markdown is not UNSET:
            field_dict["instructions_markdown"] = instructions_markdown
        if time is not UNSET:
            field_dict["time"] = time
        if order is not UNSET:
            field_dict["order"] = order
        if show_as_header is not UNSET:
            field_dict["show_as_header"] = show_as_header
        if file is not UNSET:
            field_dict["file"] = file
        if step_recipe is not UNSET:
            field_dict["step_recipe"] = step_recipe
        if step_recipe_data is not UNSET:
            field_dict["step_recipe_data"] = step_recipe_data
        if numrecipe is not UNSET:
            field_dict["numrecipe"] = numrecipe
        if show_ingredients_table is not UNSET:
            field_dict["show_ingredients_table"] = show_ingredients_table

        return field_dict

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

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

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

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

        if not isinstance(self.ingredients, Unset):
            for ingredients_item_element in self.ingredients:
                files.append(
                    ("ingredients", (None, json.dumps(ingredients_item_element.to_dict()).encode(), "application/json"))
                )

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

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

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

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

        if not isinstance(self.file, Unset):
            if self.file is None:
                files.append(("file", (None, str(self.file).encode(), "text/plain")))
            else:
                files.append(("file", (None, json.dumps(self.file.to_dict()).encode(), "application/json")))

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

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

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

        if not isinstance(self.show_ingredients_table, Unset):
            files.append(("show_ingredients_table", (None, str(self.show_ingredients_table).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.ingredient import Ingredient
        from ..models.user_file_view import UserFileView

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

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

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

        _ingredients = d.pop("ingredients", UNSET)
        ingredients: list[Ingredient] | Unset = UNSET
        if _ingredients is not UNSET:
            ingredients = []
            for ingredients_item_data in _ingredients:
                ingredients_item = Ingredient.from_dict(ingredients_item_data)

                ingredients.append(ingredients_item)

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

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

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

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

        def _parse_file(data: object) -> None | Unset | UserFileView:
            if data is None:
                return data
            if isinstance(data, Unset):
                return data
            try:
                if not isinstance(data, dict):
                    raise TypeError()
                file_type_1 = UserFileView.from_dict(data)

                return file_type_1
            except (TypeError, ValueError, AttributeError, KeyError):
                pass
            return cast(None | Unset | UserFileView, data)

        file = _parse_file(d.pop("file", UNSET))

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

        step_recipe = _parse_step_recipe(d.pop("step_recipe", UNSET))

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

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

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

        patched_step = cls(
            id=id,
            name=name,
            instruction=instruction,
            ingredients=ingredients,
            instructions_markdown=instructions_markdown,
            time=time,
            order=order,
            show_as_header=show_as_header,
            file=file,
            step_recipe=step_recipe,
            step_recipe_data=step_recipe_data,
            numrecipe=numrecipe,
            show_ingredients_table=show_ingredients_table,
        )

        patched_step.additional_properties = d
        return patched_step

    @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
