#  Copyright (C) 2023
#  ABM, Moscow
#
#  UNPUBLISHED PROPRIETARY MATERIAL.
#  ALL RIGHTS RESERVED.
#
#  Authors: Vasya Svintsov <v.svintsov@techokert.ru>
from dataclasses import dataclass, field
from enum import StrEnum, unique
from typing import Union, Any

from type_cast import convert_to_type


@unique
class ComparisonOperator(StrEnum):
    eq = '='
    equiv = '=='
    ne = '!='
    lt = '<'
    le = '<='
    ge = '>='
    gt = '>'
    in_ = 'in'
    not_in = "not_in"
    is_null = 'is_null'
    ilike = 'ilike'


@dataclass
class EntityCondition:
    attribute: str
    value: Union[int, float, bool, str, None, list[Union[int, float, bool, str]]]
    operator: ComparisonOperator


@dataclass
class EntityConditionEQ(EntityCondition):
    operator: ComparisonOperator = field(init=False, default=ComparisonOperator.eq)
    value: Union[str, int, float, bool]


@dataclass
class EntityConditionNE(EntityCondition):
    operator: ComparisonOperator = field(init=False, default=ComparisonOperator.ne)
    value: Union[str, int, float, bool]


@dataclass
class EntityConditionLT(EntityCondition):
    operator: ComparisonOperator = field(init=False, default=ComparisonOperator.lt)
    value: Union[str, int, float, bool]


@dataclass
class EntityConditionLE(EntityCondition):
    operator: ComparisonOperator = field(init=False, default=ComparisonOperator.le)
    value: Union[str, int, float, bool]


@dataclass
class EntityConditionGT(EntityCondition):
    operator: ComparisonOperator = field(init=False, default=ComparisonOperator.gt)
    value: Union[str, int, float, bool]


@dataclass
class EntityConditionGE(EntityCondition):
    operator: ComparisonOperator = field(init=False, default=ComparisonOperator.ge)
    value: Union[str, int, float, bool]


@dataclass
class EntityConditionIN(EntityCondition):
    operator: ComparisonOperator = field(init=False, default=ComparisonOperator.in_)
    value: Union[list, set]


@dataclass
class EntityConditionNotIN(EntityCondition):
    operator: ComparisonOperator = field(init=False, default=ComparisonOperator.not_in)
    value: Union[list, set]


@dataclass
class EntityConditionIsNULL(EntityCondition):
    operator: ComparisonOperator = field(init=False, default=ComparisonOperator.is_null)
    value: bool


@dataclass
class EntityConditionILIKE(EntityCondition):
    operator: ComparisonOperator = field(init=False, default=ComparisonOperator.ilike)
    value: str


def entity_condition_as_dict(condition: EntityCondition) -> dict[str, Any]:
    annotations = EntityCondition.__annotations__
    return {key: convert_to_type(type_, key, getattr(condition, key)) for key, type_ in annotations.items()}
