"""
This file is generated by the openapi-python-client tool via the generate_api_client.py script

It is a customized template from the openapi-python-client tool's default template:
https://github.com/openapi-generators/openapi-python-client/blob/861ef5622f10fc96d240dc9becb0edf94e61446c/openapi_python_client/templates/model.py.jinja

The main change is:
- Fix typing issues
"""

# flake8: noqa: C901

import datetime
from enum import Enum
from typing import Any, List, Literal, Type, TypeVar, Union, cast

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

from ..models.filter_item_field_type_0_item import FilterItemFieldType0Item
from ..models.filter_item_field_type_2_item_type_1 import FilterItemFieldType2ItemType1
from ..models.filter_item_op import FilterItemOp

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


@_attrs_define
class FilterItem:
    """
    Attributes:
        field (Union[List[FilterItemFieldType0Item], List[Union[FilterItemFieldType2ItemType1, Literal['metrics']]],
            List[Union[Literal['metadata'], str]]]):
        op (FilterItemOp):
        value (Union[List[bool], List[float], List[int], List[str], None, bool, datetime.datetime, float, int, str]):
    """

    field: Union[
        List[FilterItemFieldType0Item],
        List[Union[FilterItemFieldType2ItemType1, Literal["metrics"]]],
        List[Union[Literal["metadata"], str]],
    ]
    op: FilterItemOp
    value: Union[List[bool], List[float], List[int], List[str], None, bool, datetime.datetime, float, int, str]
    additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)

    def to_dict(self) -> dict[str, Any]:
        field: Union[List[Union[Literal["metadata"], str]], List[Union[Literal["metrics"], str]], List[str]]
        if isinstance(self.field, list):
            field = []
            for field_type_0_item_data in self.field:
                field_type_0_item = (
                    field_type_0_item_data.value if isinstance(field_type_0_item_data, Enum) else field_type_0_item_data
                )
                field.append(field_type_0_item)

        op = self.op.value if isinstance(self.op, Enum) else self.op

        value: Union[List[bool], List[float], List[int], List[str], None, bool, float, int, str]
        if isinstance(self.value, datetime.datetime):
            value = self.value.isoformat()
        elif isinstance(self.value, list):
            value = self.value

        else:
            value = self.value

        field_dict: dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update(
            {
                "field": field,
                "op": op,
                "value": value,
            }
        )

        return field_dict

    @classmethod
    def from_dict(cls: Type[T], src_dict: dict[str, Any]) -> T:
        d = src_dict.copy()

        def _parse_field(
            data: object,
        ) -> Union[
            List[FilterItemFieldType0Item],
            List[Union[FilterItemFieldType2ItemType1, Literal["metrics"]]],
            List[Union[Literal["metadata"], str]],
        ]:
            try:
                if not isinstance(data, list):
                    raise TypeError()
                field_type_0 = []
                _field_type_0 = data
                for field_type_0_item_data in _field_type_0:
                    field_type_0_item = FilterItemFieldType0Item(field_type_0_item_data)

                    field_type_0.append(field_type_0_item)

                return field_type_0
            except:  # noqa: E722
                pass
            try:
                if not isinstance(data, list):
                    raise TypeError()
                field_type_1 = []
                _field_type_1 = data
                for field_type_1_item_data in _field_type_1:

                    def _parse_field_type_1_item(data: object) -> Union[Literal["metadata"], str]:
                        field_type_1_item_type_0 = cast(Literal["metadata"], data)
                        if field_type_1_item_type_0 != "metadata":
                            raise ValueError(
                                f"field_type_1_item_type_0 must match const 'metadata', got '{field_type_1_item_type_0}'"
                            )
                        return field_type_1_item_type_0
                        return cast(Union[Literal["metadata"], str], data)

                    field_type_1_item = _parse_field_type_1_item(field_type_1_item_data)

                    field_type_1.append(field_type_1_item)

                return field_type_1
            except:  # noqa: E722
                pass
            if not isinstance(data, list):
                raise TypeError()
            field_type_2 = []
            _field_type_2 = data
            for field_type_2_item_data in _field_type_2:

                def _parse_field_type_2_item(data: object) -> Union[FilterItemFieldType2ItemType1, Literal["metrics"]]:
                    field_type_2_item_type_0 = cast(Literal["metrics"], data)
                    if field_type_2_item_type_0 != "metrics":
                        raise ValueError(
                            f"field_type_2_item_type_0 must match const 'metrics', got '{field_type_2_item_type_0}'"
                        )
                    return field_type_2_item_type_0
                    if not isinstance(data, str):
                        raise TypeError()
                    field_type_2_item_type_1 = FilterItemFieldType2ItemType1(data)

                    return field_type_2_item_type_1

                field_type_2_item = _parse_field_type_2_item(field_type_2_item_data)

                field_type_2.append(field_type_2_item)

            return field_type_2

        field = _parse_field(d.pop("field"))

        op = FilterItemOp(d.pop("op"))

        def _parse_value(
            data: object,
        ) -> Union[List[bool], List[float], List[int], List[str], None, bool, datetime.datetime, float, int, str]:
            if data is None:
                return data
            try:
                if not isinstance(data, str):
                    raise TypeError()
                value_type_4 = isoparse(data)

                return value_type_4
            except:  # noqa: E722
                pass
            try:
                if not isinstance(data, list):
                    raise TypeError()
                value_type_5 = cast(List[str], data)

                return value_type_5
            except:  # noqa: E722
                pass
            try:
                if not isinstance(data, list):
                    raise TypeError()
                value_type_6 = cast(List[int], data)

                return value_type_6
            except:  # noqa: E722
                pass
            try:
                if not isinstance(data, list):
                    raise TypeError()
                value_type_7 = cast(List[float], data)

                return value_type_7
            except:  # noqa: E722
                pass
            try:
                if not isinstance(data, list):
                    raise TypeError()
                value_type_8 = cast(List[bool], data)

                return value_type_8
            except:  # noqa: E722
                pass
            return cast(
                Union[List[bool], List[float], List[int], List[str], None, bool, datetime.datetime, float, int, str],
                data,
            )

        value = _parse_value(d.pop("value"))

        filter_item = cls(
            field=field,
            op=op,
            value=value,
        )

        filter_item.additional_properties = d
        return filter_item

    @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
