from collections.abc import Hashable
from typing import overload

import numpy as np
import pandas as pd
from pandas import Index
from pandas.core.indexes.accessors import PeriodIndexFieldOps
from pandas.core.indexes.datetimelike import (
    DatetimeIndexOpsMixin as DatetimeIndexOpsMixin,
)
from pandas.core.indexes.numeric import Int64Index
from pandas.core.series import OffsetSeries

from pandas._libs.tslibs import (
    BaseOffset,
    Period,
)

class PeriodIndex(DatetimeIndexOpsMixin, Int64Index, PeriodIndexFieldOps):
    def __new__(
        cls,
        data=...,
        ordinal=...,
        freq=...,
        tz=...,
        dtype=...,
        copy: bool = ...,
        name=...,
        **fields,
    ): ...
    @property
    def values(self): ...
    def __contains__(self, key) -> bool: ...
    # Override due to supertype incompatibility which has it for NumericIndex or complex.
    @overload  # type: ignore[override]
    def __sub__(self, other: Period) -> Index: ...
    @overload
    def __sub__(self, other: PeriodIndex) -> OffsetSeries: ...
    def __array__(self, dtype=...) -> np.ndarray: ...
    def __array_wrap__(self, result, context=...): ...
    def asof_locs(self, where, mask): ...
    def astype(self, dtype, copy: bool = ..., how: str = ...): ...
    def searchsorted(self, value, side: str = ..., sorter=...): ...
    @property
    def is_full(self) -> bool: ...
    @property
    def inferred_type(self) -> str: ...
    def get_value(self, series, key): ...
    def get_indexer(self, target, method=..., limit=..., tolerance=...): ...
    def get_indexer_non_unique(self, target): ...
    def get_loc(self, key, tolerance=...): ...
    def insert(self, loc, item): ...
    def join(
        self,
        other,
        *,
        how: str = ...,
        level=...,
        return_indexers: bool = ...,
        sort: bool = ...,
    ): ...
    def intersection(self, other, sort: bool = ...): ...
    def difference(self, other, sort=...): ...
    def memory_usage(self, deep: bool = ...): ...
    @property
    def freqstr(self) -> str: ...

def period_range(
    start: str | pd.Period | None = ...,
    end: str | pd.Period | None = ...,
    periods: int | None = ...,
    freq: str | BaseOffset | None = ...,
    name: Hashable | None = ...,
) -> PeriodIndex: ...
