from typing import Union
import inspect
from typing import Callable
from typing import Dict
from typing import Any


def add_named_kwargs_to_signature(
    func_or_signature: Union[inspect.Signature, Callable],
    kwargs: Dict[str, Any]
) -> inspect.Signature:
    """
    Add named keyword arguments with default values to a function signature.

    Parameters
    ----------
    func_or_signature : inspect.Signature or callable
        The function or signature.

    kwargs : dict
        The dictionary of kwarg_name to default_value.

    Returns
    -------
    modified_signature : inspect.Signature
        The modified signature with additional keyword arguments.
    """

    if isinstance(func_or_signature, inspect.Signature):
        sig = func_or_signature
    else:
        sig = inspect.signature(func_or_signature)

    params = list(sig.parameters.values())
    keyword_only_indices = [
        idx for idx, param in enumerate(params)
        if param.kind == inspect.Parameter.KEYWORD_ONLY
    ]
    if not keyword_only_indices:
        start_params, end_params = params, []
    else:
        insert_at = keyword_only_indices[0]
        start_params, end_params = params[:insert_at], params[insert_at:]

    wrapper_params = list(
        inspect.Parameter(
            name, kind=inspect.Parameter.KEYWORD_ONLY, default=value
        )
        for name, value in kwargs.items()
        if name not in sig.parameters
    )

    return sig.replace(parameters=start_params + wrapper_params + end_params)