import typing
from datetime import tzinfo
from typing import Callable
from typing import ClassVar as _ClassVar

from ._bases_meta import ALLOWED_MODES, HookFn, PreDecoder
from ._decorators import cached_class_property as cached_class_property
from ._path_util import EnvFilePaths, SecretsDirs
from ._type_def import META
from .conditions import Condition
from .enums import DateTimeTo as DateTimeTo
from .enums import EnvKeyStrategy as EnvKeyStrategy
from .enums import EnvPrecedence as EnvPrecedence
from .enums import KeyAction as KeyAction
from .enums import KeyCase as KeyCase

TypeToHook = typing.Mapping[
    type, tuple[ALLOWED_MODES, HookFn] | HookFn | None]

class ABCOrAndMeta(type):
    @classmethod
    def __and__(cls: META, other: META) -> META: ...
    @classmethod
    def merge(cls: META, other: META) -> META: ...

class BaseMeta:
    __special_attrs__: _ClassVar[frozenset] = ...
    __is_inner_meta__: _ClassVar[bool] = ...
    recursive: _ClassVar[bool] = ...
    tag: _ClassVar[str | None] = ...
    tag_key: _ClassVar[str] = ...
    auto_assign_tags: _ClassVar[bool] = ...
    skip_defaults: _ClassVar[bool] = ...
    skip_if: _ClassVar[Condition | None] = ...
    skip_defaults_if: _ClassVar[Condition | None] = ...
    debug: _ClassVar[bool | int | str] = ...
    type_to_load_hook: _ClassVar[TypeToHook | None] = ...
    type_to_dump_hook: _ClassVar[TypeToHook | None] = ...
    pre_decoder: _ClassVar[PreDecoder] = ...
    dump_case: _ClassVar[KeyCase | str | None] = ...
    field_to_alias_dump: _ClassVar[
        typing.Mapping[str, str | typing.Sequence[str]] | None] = ...
    unsafe_parse_dataclass_in_union: _ClassVar[bool] = ...
    dump_date_time_as: _ClassVar[DateTimeTo | str | None] = ...
    assume_naive_datetime_tz: _ClassVar[tzinfo | None] = ...
    namedtuple_as_dict: _ClassVar[bool | None] = ...
    coerce_none_to_empty_str: _ClassVar[bool | None] = ...
    leaf_handling: _ClassVar[
        typing.Literal['exact', 'issubclass'] | None] = ...
    all_fields: _ClassVar[frozenset] = ...
    fields_to_merge: _ClassVar[frozenset] = ...

class AbstractMeta(BaseMeta):
    __special_attrs__: _ClassVar[frozenset] = ...
    __is_inner_meta__: _ClassVar[bool] = ...
    case: _ClassVar[KeyCase | str | None] = ...
    load_case: _ClassVar[KeyCase | str | None] = ...
    field_to_alias: _ClassVar[
        typing.Mapping[str, str | typing.Sequence[str]] | None] = ...
    field_to_alias_load: _ClassVar[
        typing.Mapping[str, str | typing.Sequence[str]] | None] = ...
    on_unknown_key: _ClassVar[KeyAction | None] = ...
    @classmethod
    def bind_to(
        cls, dataclass: type, create: bool = ..., is_default: bool = ...): ...

class AbstractEnvMeta(BaseMeta):
    __special_attrs__: _ClassVar[frozenset] = ...
    __is_inner_meta__: _ClassVar[bool] = ...
    env_file: _ClassVar[EnvFilePaths] = ...
    env_prefix: _ClassVar[str | None] = ...
    secrets_dir: _ClassVar[SecretsDirs] = ...
    load_case: _ClassVar[EnvKeyStrategy | str | None] = ...
    env_precedence: _ClassVar[EnvPrecedence | None] = ...
    field_to_env_load: _ClassVar[
        typing.Mapping[str, str | typing.Sequence[str]] | None] = ...
    @classmethod
    def bind_to(
        cls, env_class: type, create: bool = ..., is_default: bool = ...): ...

class _BaseHookRegistry:
    @classmethod
    def register_hook(cls, typ: type, func: Callable): ...
    @classmethod
    def get_hook(cls, typ: type) -> Callable | None: ...

class BaseLoadHook(_BaseHookRegistry):
    __HOOKS__: _ClassVar[dict[type, Callable]]

class BaseDumpHook(_BaseHookRegistry):
    __HOOKS__: _ClassVar[dict[type, Callable]]
