from __future__ import annotations

from typing import Any, Sequence

__version__: str


class PruningStats:
    @property
    def candidates_considered(self) -> int: ...
    @property
    def candidates_pruned(self) -> int: ...


class SegmentStats:
    @property
    def start(self) -> int: ...
    @property
    def end(self) -> int: ...
    @property
    def mean(self) -> list[float] | None: ...
    @property
    def variance(self) -> list[float] | None: ...
    @property
    def count(self) -> int: ...
    @property
    def missing_count(self) -> int: ...


class Diagnostics:
    @property
    def n(self) -> int: ...
    @property
    def d(self) -> int: ...
    @property
    def schema_version(self) -> int: ...
    @property
    def engine_version(self) -> str | None: ...
    @property
    def runtime_ms(self) -> int | None: ...
    @property
    def notes(self) -> list[str]: ...
    @property
    def warnings(self) -> list[str]: ...
    @property
    def algorithm(self) -> str: ...
    @property
    def cost_model(self) -> str: ...
    @property
    def seed(self) -> int | None: ...
    @property
    def repro_mode(self) -> str: ...
    @property
    def thread_count(self) -> int | None: ...
    @property
    def blas_backend(self) -> str | None: ...
    @property
    def cpu_features(self) -> list[str] | None: ...
    @property
    def params_json(self) -> Any | None: ...
    @property
    def pruning_stats(self) -> PruningStats | None: ...
    @property
    def missing_policy_applied(self) -> str | None: ...
    @property
    def missing_fraction(self) -> float | None: ...
    @property
    def effective_sample_count(self) -> int | None: ...


class OfflineChangePointResult:
    @property
    def breakpoints(self) -> list[int]: ...
    @property
    def change_points(self) -> list[int]: ...
    @property
    def scores(self) -> list[float] | None: ...
    @property
    def segments(self) -> list[SegmentStats] | None: ...
    @property
    def diagnostics(self) -> Diagnostics: ...
    def to_json(self) -> str: ...
    @staticmethod
    def from_json(payload: str) -> OfflineChangePointResult: ...
    def plot(
        self,
        values: Any | None = None,
        *,
        ax: Any | None = None,
        title: str | None = None,
        breakpoint_color: str = "crimson",
        breakpoint_style: str = "--",
        line_width: float = 1.5,
        show_legend: bool = True,
    ) -> Any: ...


class OnlineStepResult:
    @property
    def t(self) -> int: ...
    @property
    def p_change(self) -> float: ...
    @property
    def alert(self) -> bool: ...
    @property
    def alert_reason(self) -> str | None: ...
    @property
    def run_length_mode(self) -> int: ...
    @property
    def run_length_mean(self) -> float: ...
    @property
    def processing_latency_us(self) -> int | None: ...


class _BocpdState: ...


class _CusumState: ...


class _PageHinkleyState: ...


class Pelt:
    def __init__(
        self,
        model: str = "l2",
        min_segment_len: int = 2,
        jump: int = 1,
        max_change_points: int | None = None,
    ) -> None: ...
    def fit(self, values: Any) -> Pelt: ...
    def predict(
        self, *, pen: float | None = None, n_bkps: int | None = None
    ) -> OfflineChangePointResult: ...


class Binseg:
    def __init__(
        self,
        model: str = "l2",
        min_segment_len: int = 2,
        jump: int = 1,
        max_change_points: int | None = None,
        max_depth: int | None = None,
    ) -> None: ...
    def fit(self, values: Any) -> Binseg: ...
    def predict(
        self, *, pen: float | None = None, n_bkps: int | None = None
    ) -> OfflineChangePointResult: ...


class Fpop:
    def __init__(
        self,
        min_segment_len: int = 2,
        jump: int = 1,
        max_change_points: int | None = None,
    ) -> None: ...
    def fit(self, values: Any) -> Fpop: ...
    def predict(
        self, *, pen: float | None = None, n_bkps: int | None = None
    ) -> OfflineChangePointResult: ...


class Bocpd:
    def __init__(
        self,
        model: str = "gaussian_nig",
        hazard: float | dict[str, Any] | None = None,
        max_run_length: int = 2000,
        alert_policy: dict[str, Any] | None = None,
        late_data_policy: str | dict[str, Any] | None = None,
    ) -> None: ...
    def update(self, x_t: float, t_ns: int | None = None) -> OnlineStepResult: ...
    def update_many(self, x_batch: Any) -> list[OnlineStepResult]: ...
    def reset(self) -> None: ...
    def save_state(
        self, *, format: str = "bytes", path: str | Any | None = None
    ) -> bytes | dict[str, Any] | None: ...
    def load_state(
        self,
        state: bytes | dict[str, Any] | _BocpdState | None = None,
        *,
        format: str | None = None,
        path: str | Any | None = None,
    ) -> None: ...


class Cusum:
    def __init__(
        self,
        drift: float = 0.0,
        threshold: float = 8.0,
        target_mean: float = 0.0,
        alert_policy: dict[str, Any] | None = None,
        late_data_policy: str | dict[str, Any] | None = None,
    ) -> None: ...
    def update(self, x_t: float, t_ns: int | None = None) -> OnlineStepResult: ...
    def update_many(self, x_batch: Any) -> list[OnlineStepResult]: ...
    def reset(self) -> None: ...
    def save_state(
        self, *, format: str = "bytes", path: str | Any | None = None
    ) -> bytes | dict[str, Any] | None: ...
    def load_state(
        self,
        state: bytes | dict[str, Any] | _CusumState | None = None,
        *,
        format: str | None = None,
        path: str | Any | None = None,
    ) -> None: ...


class PageHinkley:
    def __init__(
        self,
        delta: float = 0.01,
        threshold: float = 8.0,
        initial_mean: float = 0.0,
        alert_policy: dict[str, Any] | None = None,
        late_data_policy: str | dict[str, Any] | None = None,
    ) -> None: ...
    def update(self, x_t: float, t_ns: int | None = None) -> OnlineStepResult: ...
    def update_many(self, x_batch: Any) -> list[OnlineStepResult]: ...
    def reset(self) -> None: ...
    def save_state(
        self, *, format: str = "bytes", path: str | Any | None = None
    ) -> bytes | dict[str, Any] | None: ...
    def load_state(
        self,
        state: bytes | dict[str, Any] | _PageHinkleyState | None = None,
        *,
        format: str | None = None,
        path: str | Any | None = None,
    ) -> None: ...


class SmokeDetector:
    def __init__(self) -> None: ...
    def fit(self, values: Sequence[float]) -> SmokeDetector: ...
    def predict(self) -> list[int]: ...


def detect_offline(
    values: Any,
    *,
    pipeline: dict[str, Any] | None = None,
    detector: str = "pelt",
    cost: str = "l2",
    constraints: dict[str, Any] | None = None,
    stopping: dict[str, Any] | None = None,
    preprocess: dict[str, Any] | None = None,
    repro_mode: str = "balanced",
    return_diagnostics: bool = True,
) -> OfflineChangePointResult: ...


def smoke_detect(values: Sequence[float]) -> list[int]: ...
