"""Deprecation helpers for stable public API management."""

from __future__ import annotations

from collections.abc import Callable
from functools import wraps
import warnings
from typing import Any, TypeVar, cast


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


def deprecated(
    *,
    since: str,
    remove_in: str,
    replacement: str | None = None,
    details: str | None = None,
) -> Callable[[F], F]:
    """Mark a callable as deprecated with a consistent warning payload."""

    def decorator(func: F) -> F:
        message = f"{func.__name__} is deprecated since {since} and will be removed in {remove_in}."
        if replacement:
            message += f" Use {replacement} instead."
        if details:
            message += f" {details}"

        @wraps(func)
        def wrapper(*args: Any, **kwargs: Any):
            warnings.warn(message, DeprecationWarning, stacklevel=2)
            return func(*args, **kwargs)

        return cast(F, wrapper)

    return decorator
