from __future__ import annotations

from datetime import datetime, timedelta
from typing import Any, Callable, Literal, Type, TypeVar

from wombat.multiprocessing.traits.models import BaseTrait, Task

F = TypeVar("F", bound=Callable[..., Any])
Decorator = Callable[[F], Callable[..., Task]]

def register_trait_decorator(
    trait_cls: Type[BaseTrait],
) -> Callable[..., Decorator]: ...
def task() -> Decorator: ...
def retryable(
    *,
    max_tries: int = ...,
    initial_delay: float = ...,
    max_delay: float = ...,
    backoff_strategy: Literal["exponential", "simple", "custom"] = ...,
    backoff_multiplier: float = ...,
    backoff_function: Callable[[Any], float] | None = ...,
) -> Decorator: ...
def evaluatable(*, evaluator: Callable[[Any], bool] | None = ...) -> Decorator: ...
def expirable(
    *,
    expires_at: datetime | None = ...,
    expires_after: timedelta | None = ...,
) -> Decorator: ...
def loggable(*, log_level: int = ...) -> Decorator: ...
def progress(*, weight: int = ...) -> Decorator: ...
def requires_props(
    *, requires_props: list[str] = ..., include_all_props: bool = ...
) -> Decorator: ...
def timelimit(*, timeout: float) -> Decorator: ...
def debounce(*, window: timedelta = ...) -> Decorator: ...
def breaker(
    *, failure_threshold: int = ..., recovery_timeout: float = ...
) -> Decorator: ...
def produces(*, must_have_traits: list[str] | None = ...) -> Decorator: ...
def throttled(*, limit: int = ..., period: float = ...) -> Decorator: ...
