from collections.abc import Iterable, Mapping
from typing import Any, cast

from ....typedefs import FieldValue


def extract_field(data: Any, field_key: str) -> FieldValue:
    if isinstance(data, Mapping):
        # NOTE: `isinstance(data, Mapping)` narrows to `Mapping[Unknown, Unknown]` in basedpyright,
        # which makes `get()` partially-unknown. We intentionally treat mapping keys as strings here.
        mapping = cast("Mapping[str, Any]", data)
        return cast("FieldValue", mapping.get(field_key))

    try:
        return cast("FieldValue", object.__getattribute__(data, field_key))  # type: ignore[call-arg]
    except AttributeError:
        pass

    try:
        return cast("FieldValue", data[field_key])
    except (LookupError, TypeError):
        return None


def contains_float(value: Any) -> bool:
    if isinstance(value, float):
        return True
    if isinstance(value, (list, tuple)):
        for item in cast("Iterable[Any]", value):
            if isinstance(item, float):
                return True
    return False
