import functools
import inspect
import logging
import warnings

from pytools.utils import get_class_name

logger = logging.getLogger(__name__)


def deprecated(reason: str = ""):
    """
    Decorator to mark functions/methods as deprecated.
    Logs the class name if decorating a method.
    Supports async and sync functions.
    """

    def decorator(func):
        is_async = inspect.iscoroutinefunction(func)

        if is_async:

            @functools.wraps(func)
            async def wrapper(*args, **kwargs):
                cls_name = get_class_name(args)
                msg = f"{cls_name + '.' if cls_name else ''}{func.__name__} is deprecated. {reason}"
                warnings.warn(msg, DeprecationWarning, stacklevel=2)
                logger.warning(msg)
                return await func(*args, **kwargs)
        else:

            @functools.wraps(func)
            def wrapper(*args, **kwargs):
                cls_name = get_class_name(args)
                msg = f"{cls_name + '.' if cls_name else ''}{func.__name__} is deprecated. {reason}"
                warnings.warn(msg, DeprecationWarning, stacklevel=2)
                logger.warning(msg)
                return func(*args, **kwargs)

        return wrapper

    return decorator
