#  Copyright (C) 2023
#  ABM, Moscow
#
#  UNPUBLISHED PROPRIETARY MATERIAL.
#  ALL RIGHTS RESERVED.
#
#  Authors: Vasiliev Ivan <i.vasiliev@technokert.ru>
from dataclasses import dataclass, field
from typing import Iterable, Callable

from ....elements.filter_by import Condition as ChCondition, ComparisonOperator, Filter
from ....elements.column import Column
from ..base import AbstractFactory
from .abstract_function import AbstractFunction


@dataclass
class Comparison(AbstractFunction):

    def __post_init__(self):
        self.name = self.name.lower()

    def call(self, left: Column, right: str | int | list) -> ChCondition | Filter:
        return Filter(attribute=left, value=right, operator=getattr(ComparisonOperator, self.name))


@dataclass
class Condition(AbstractFunction):
    condition: ChCondition = field(init=False, default_factory=ChCondition,)

    def call(self, *condition_args: Iterable) -> ChCondition:
        handler = self._choose_handler()
        for arg in condition_args:
            handler(arg)
        return self.condition

    def _choose_handler(self) -> Callable:
        if self.name == "or":
            return self.condition.add_or
        if self.name == "and":
            return self.condition.add_and
        raise KeyError(f"unknown handler for {self.name}")


class ConditionFactory(AbstractFactory):
    condition_keys = {"or", "and"}
    comparison_keys = {comparison_name for comparison_name in ComparisonOperator.get_member_names()}
    comparison_name_to_replacement = {
        "in": "in_"
    }

    def __getattr__(self, key: str) -> Condition | Comparison:
        if key in self.comparison_name_to_replacement:
            key = self.comparison_name_to_replacement[key]
        if key in self.condition_keys:
            return Condition(key)
        elif key in self.comparison_keys:
            return Comparison(key)
        raise KeyError(f"unknown condition :{key}, allowed: {self.condition_keys.union(self.comparison_keys)}")
