from typing import Union
from typing import Callable
from typing import Any
from typing import Optional
from typing import Tuple
from typing import Dict


def format_callback_to_string(
    callback: Union[str, Callable[..., Any]],
    args: Optional[Tuple[Any, ...]] = None,
    kwargs: Optional[Dict[str, Any]] = None,
) -> str:
    """
    Convert a callback, its arguments and keyword arguments to a string suitable for logging purposes.

    Arguments:
        callback:
            The callback function

    Keyword Arguments:
        args:
            The callback arguments
        kwargs:
            The callback keyword arguments

    Returns:
        str: The formatted callback string
    """
    callback_str = None
    if not isinstance(callback, str):
        try:
            callback_str = '{0}('.format(callback.__qualname__)
        except AttributeError:
            callback_str = '{0}('.format(callback.__name__)
    else:
        callback_str = '{0}('.format(callback)
    if args:
        callback_str += ', '.join([repr(arg) for arg in args])
    if kwargs:
        if args:
            callback_str += ', '
        callback_str += ', '.join(['{0}={1}'.format(k, v) for k, v in kwargs.items()])
    callback_str += ')'
    return callback_str