from __future__ import annotations

from collections.abc import Container, Iterable
from typing import TYPE_CHECKING

from liblaf.grapes import warnings

if TYPE_CHECKING:
    from _typeshed import SupportsGetItem


_DEPRECATED_MESSAGE = "'{deprecated_key}' is deprecated. Please use '{key}' instead."


def contains[T](
    obj: Container[T],
    key: T,
    deprecated_keys: Iterable[T] = (),
    *,
    msg: str = _DEPRECATED_MESSAGE,
) -> bool:
    """.

    Examples:
        >>> import pytest
        >>> data = {"a": 1, "b": 2}
        >>> contains(data, "a")
        True
        >>> contains(data, "missing")
        False
        >>> with pytest.deprecated_call():
        ...     contains(data, "c", deprecated_keys=["missing", "b"])
        True
    """
    _warnings_hide = True
    if key in obj:
        return True
    for deprecated_key in deprecated_keys:
        if deprecated_key in obj:
            warnings.warn(
                msg.format_map({"deprecated_key": deprecated_key, "key": key}),
                DeprecationWarning,
            )
            return True
    return False


def getitem[KT, VT](
    obj: SupportsGetItem[KT, VT],
    key: KT,
    deprecated_keys: Iterable[KT] = (),
    *,
    msg: str = _DEPRECATED_MESSAGE,
) -> VT:
    """.

    Examples:
        >>> import pytest
        >>> data = {"a": 1, "b": 2}
        >>> getitem(data, "a")
        1
        >>> with pytest.raises(KeyError):
        ...     getitem(data, "missing")
        >>> with pytest.deprecated_call():
        ...     getitem(data, "c", deprecated_keys=["missing", "b"])
        2
    """
    _warnings_hide = True
    try:
        return obj[key]
    except KeyError:
        pass
    for deprecated_key in deprecated_keys:
        try:
            value: VT = obj[deprecated_key]
        except KeyError:
            continue
        warnings.warn(
            msg.format_map({"deprecated_key": deprecated_key, "key": key}),
            DeprecationWarning,
        )
        return value
    raise KeyError(key)
