from collections.abc import Callable
from typing import (
    Any,
    Literal,
    Self,
    overload,
)

import numpy as np
from pandas.core.arrays.boolean import BooleanArray
from pandas.core.indexes.base import Index
from pandas.core.series import Series

from pandas._typing import Scalar

class NAType:
    def __new__(cls, *args: Any, **kwargs: Any) -> Self: ...
    def __format__(self, format_spec: str) -> str: ...
    def __hash__(self) -> int: ...
    def __reduce__(self) -> str: ...
    @overload
    def __add__(self, other: Series, /) -> Series: ...
    @overload
    def __add__(self, other: Index, /) -> Index: ...
    @overload
    def __add__(self, other: Scalar, /) -> NAType: ...
    @overload
    def __radd__(self, other: Series, /) -> Series: ...
    @overload
    def __radd__(self, other: Index, /) -> Index: ...
    @overload
    def __radd__(self, other: Scalar, /) -> NAType: ...
    @overload
    def __sub__(self, other: Series, /) -> Series: ...
    @overload
    def __sub__(self, other: Index, /) -> Index: ...
    @overload
    def __sub__(self, other: Scalar, /) -> NAType: ...
    @overload
    def __rsub__(self, other: Series, /) -> Series: ...
    @overload
    def __rsub__(self, other: Index, /) -> Index: ...
    @overload
    def __rsub__(self, other: Scalar, /) -> NAType: ...
    @overload
    def __mul__(self, other: Series, /) -> Series: ...
    @overload
    def __mul__(self, other: Index, /) -> Index: ...
    @overload
    def __mul__(self, other: Scalar, /) -> NAType: ...
    @overload
    def __rmul__(self, other: Series, /) -> Series: ...
    @overload
    def __rmul__(self, other: Index, /) -> Index: ...
    @overload
    def __rmul__(self, other: Scalar, /) -> NAType: ...
    def __matmul__(self, other: Scalar, /) -> NAType: ...
    def __rmatmul__(self, other: Scalar, /) -> NAType: ...
    @overload
    def __truediv__(self, other: Series, /) -> Series: ...
    @overload
    def __truediv__(self, other: Index, /) -> Index: ...
    @overload
    def __truediv__(self, other: Scalar, /) -> NAType: ...
    @overload
    def __rtruediv__(self, other: Series, /) -> Series: ...
    @overload
    def __rtruediv__(self, other: Index, /) -> Index: ...
    @overload
    def __rtruediv__(self, other: Scalar, /) -> NAType: ...
    @overload
    def __floordiv__(self, other: Series, /) -> Series: ...
    @overload
    def __floordiv__(self, other: Index, /) -> Index: ...
    @overload
    def __floordiv__(self, other: Scalar, /) -> NAType: ...
    @overload
    def __rfloordiv__(self, other: Series, /) -> Series: ...
    @overload
    def __rfloordiv__(self, other: Index, /) -> Index: ...
    @overload
    def __rfloordiv__(self, other: Scalar, /) -> NAType: ...
    @overload
    def __mod__(self, other: Series, /) -> Series: ...
    @overload
    def __mod__(self, other: Index, /) -> Index: ...
    @overload
    def __mod__(self, other: Scalar, /) -> NAType: ...
    @overload
    def __rmod__(self, other: Series, /) -> Series: ...
    @overload
    def __rmod__(self, other: Index, /) -> Index: ...
    @overload
    def __rmod__(self, other: Scalar, /) -> NAType: ...
    @overload
    def __divmod__(self, other: Series, /) -> tuple[Series, Series]: ...
    @overload
    def __divmod__(self, other: Index, /) -> tuple[Index, Index]: ...
    @overload
    def __divmod__(self, other: Scalar, /) -> tuple[NAType, NAType]: ...
    @overload
    def __rdivmod__(self, other: Series, /) -> tuple[Series, Series]: ...
    @overload
    def __rdivmod__(self, other: Index, /) -> tuple[Index, Index]: ...
    @overload
    def __rdivmod__(self, other: Scalar, /) -> tuple[NAType, NAType]: ...
    @overload  # type: ignore[override]
    def __eq__(  # pyrefly: ignore[bad-override]
        self, other: Series, /
    ) -> Series[bool]: ...
    @overload
    def __eq__(self, other: Index, /) -> BooleanArray: ...
    @overload
    def __eq__(  # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override]
        self, other: Scalar, /
    ) -> NAType: ...
    @overload  # type: ignore[override]
    def __ne__(  # pyrefly: ignore[bad-override]
        self, other: Series, /
    ) -> Series[bool]: ...
    @overload
    def __ne__(self, other: Index, /) -> BooleanArray: ...
    @overload
    def __ne__(  # pyright: ignore[reportIncompatibleMethodOverride] # ty: ignore[invalid-method-override]
        self, other: Scalar, /
    ) -> NAType: ...
    @overload
    def __le__(self, other: Series, /) -> Series[bool]: ...
    @overload
    def __le__(self, other: Index, /) -> BooleanArray: ...
    @overload
    def __le__(self, other: Scalar, /) -> NAType: ...
    @overload
    def __lt__(self, other: Series, /) -> Series[bool]: ...
    @overload
    def __lt__(self, other: Index, /) -> BooleanArray: ...
    @overload
    def __lt__(self, other: Scalar, /) -> NAType: ...
    @overload
    def __gt__(self, other: Series, /) -> Series[bool]: ...
    @overload
    def __gt__(self, other: Index, /) -> BooleanArray: ...
    @overload
    def __gt__(self, other: Scalar, /) -> NAType: ...
    @overload
    def __ge__(self, other: Series, /) -> Series[bool]: ...
    @overload
    def __ge__(self, other: Index, /) -> BooleanArray: ...
    @overload
    def __ge__(self, other: Scalar, /) -> NAType: ...
    def __neg__(self) -> NAType: ...
    def __pos__(self) -> NAType: ...
    def __abs__(self) -> NAType: ...
    def __invert__(self) -> NAType: ...
    @overload
    def __pow__(self, other: Series, /) -> Series: ...
    @overload
    def __pow__(self, other: Index, /) -> Index: ...
    @overload
    def __pow__(self, other: complex, /) -> NAType: ...
    @overload
    def __rpow__(self, other: Series, /) -> Series: ...
    @overload
    def __rpow__(self, other: Index, /) -> Index: ...
    @overload
    def __rpow__(self, other: complex, /) -> NAType: ...
    @overload
    def __and__(self, other: Literal[False], /) -> Literal[False]: ...  # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
    @overload
    def __and__(self, other: bool | NAType, /) -> NAType: ...
    @overload
    def __rand__(self, other: Literal[False], /) -> Literal[False]: ...  # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
    @overload
    def __rand__(self, other: bool, /) -> NAType: ...
    @overload
    def __or__(self, other: Literal[True], /) -> Literal[True]: ...  # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
    @overload
    def __or__(self, other: bool | NAType, /) -> NAType: ...
    @overload
    def __ror__(self, other: Literal[True], /) -> Literal[True]: ...  # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
    @overload
    def __ror__(self, other: bool | NAType, /) -> NAType: ...
    @overload
    def __xor__(self, other: Series, /) -> Series: ...
    @overload
    def __xor__(self, other: Index, /) -> Index: ...
    @overload
    def __xor__(self, other: bool | np.bool, /) -> NAType: ...
    @overload
    def __rxor__(self, other: Series, /) -> Series: ...
    @overload
    def __rxor__(self, other: Index, /) -> Index: ...
    @overload
    def __rxor__(self, other: bool | np.bool, /) -> NAType: ...
    __array_priority__: int
    def __array_ufunc__(
        self, ufunc: Callable[..., Any], method: str, *inputs: Any, **kwargs: Any
    ) -> Any: ...

NA: NAType
