###  Договоренности по именованию json-функций следующие
###  Все названия из постгри переводим в свой регистр, а в названиях с path, использующих jsonpath,
###  заменяем path на jsonpath. Для операторов, не имеющих имени построим его на описании, сохраняя уникальность, тогда:
###  -> FunctionJsonExtract
###  ->> FunctionJsonExtractText
###  #> FunctionJsonExtractPath
###  #>> FunctionJsonExtractPathText
###  @> FunctionJsonContains
###  <@ FunctionJsonContainedBy
###  ? FunctionJsonHasKey
###  ?| FunctionJsonHasAnyKey
###  ?& FunctionJsonHasAllKeys
###  || FunctionJsonConcat
###  - FunctionJsonDelete
###  #-  FunctionJsonDeletePath
###  @? FunctionJsonJsonpathExists
###  @@ FunctionJsonJsonpathMatch

### Описание json-операторов в документации postgres: https://www.postgresql.org/docs/9.5/functions-json.html
### Функции jpath: https://www.postgresql.org/docs/current/functions-json.html#FUNCTIONS-SQLJSON-CHECK-EXPRESSIONS
from dataclasses import dataclass, field
from typing import ClassVar, Any

from entity_read.sql.atoms import Function, Selectable


@dataclass(kw_only=True, frozen=True)
class FunctionJsonExtractText(Function):
    type_: str = field(default=str, init=False)
    args: tuple[Selectable[Any]]
    code: ClassVar[str] = 'json_extract_text'

    def _to_sql(self, args_sql: list) -> str:
        return f"{args_sql[0]} ->> {args_sql[1]}"


@dataclass(kw_only=True, frozen=True)
class FunctionJsonHasKey(Function):
    type_: str = field(default=str, init=False)
    args: tuple[Selectable[Any]]
    code: ClassVar[str] = 'json_has_key'

    def _to_sql(self, args_sql: list):
        return f"{args_sql[0]} ? {args_sql[1]}"
