from typing import overload

import numpy as np
from pandas import (
    Index,
    Series,
)
from pandas.core.arrays.base import ExtensionArray as ExtensionArray
from typing_extensions import (
    Self,
    TypeAlias,
)

from pandas._libs.interval import (
    Interval as Interval,
    IntervalMixin as IntervalMixin,
)
from pandas._typing import (
    Axis,
    Scalar,
    ScalarIndexer,
    SequenceIndexer,
    TakeIndexer,
    np_1darray,
)

IntervalOrNA: TypeAlias = Interval | float

class IntervalArray(IntervalMixin, ExtensionArray):
    can_hold_na: bool = ...
    def __new__(
        cls, data, closed=..., dtype=..., copy: bool = ..., verify_integrity: bool = ...
    ): ...
    @classmethod
    def from_breaks(
        cls,
        breaks,
        closed: str = "right",
        copy: bool = False,
        dtype=None,
    ): ...
    @classmethod
    def from_arrays(
        cls,
        left,
        right,
        closed: str = "right",
        copy: bool = False,
        dtype=...,
    ): ...
    @classmethod
    def from_tuples(
        cls,
        data,
        closed: str = "right",
        copy: bool = False,
        dtype=None,
    ): ...
    def __iter__(self): ...
    def __len__(self) -> int: ...
    @overload
    def __getitem__(self, key: ScalarIndexer) -> IntervalOrNA: ...
    @overload
    def __getitem__(self, key: SequenceIndexer) -> Self: ...
    def __setitem__(self, key, value) -> None: ...
    def __eq__(self, other): ...
    def __ne__(self, other): ...
    def fillna(self, value=..., method=None, limit=None): ...
    @property
    def dtype(self): ...
    def astype(self, dtype, copy: bool = True): ...
    def copy(self): ...
    def isna(self): ...
    @property
    def nbytes(self) -> int: ...
    @property
    def size(self) -> int: ...
    def shift(self, periods: int = 1, fill_value: object = ...) -> IntervalArray: ...
    def take(  # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
        self: Self,
        indices: TakeIndexer,
        *,
        allow_fill: bool = ...,
        fill_value=...,
        axis=...,
        **kwargs,
    ) -> Self: ...
    def value_counts(self, dropna: bool = True): ...
    @property
    def left(self) -> Index: ...
    @property
    def right(self) -> Index: ...
    @property
    def closed(self) -> bool: ...
    def set_closed(self, closed): ...
    @property
    def length(self) -> Index: ...
    @property
    def mid(self) -> Index: ...
    @property
    def is_non_overlapping_monotonic(self) -> bool: ...
    def __array__(self, dtype=...) -> np_1darray: ...
    def __arrow_array__(self, type=...): ...
    def to_tuples(self, na_tuple: bool = True): ...
    def repeat(self, repeats, axis: Axis | None = ...): ...
    @overload
    def contains(self, other: Series) -> Series[bool]: ...
    @overload
    def contains(
        self, other: Scalar | ExtensionArray | Index | np.ndarray
    ) -> np_1darray[np.bool]: ...
    def overlaps(self, other: Interval) -> bool: ...
