import importlib
import inspect


def _ensure_class(class_or_class_name, compatible_class=None):
    """
    Ensure that the supplied value is either a class or a fully-qualified class name.

    :param name: A class or a fully-qualified class name.
    :param expected_base_class: If specified then the class must be, or (eventually) derive from, this class.
    :return: The class represented by class_or_class_name.
    """

    target_class = class_or_class_name
    if isinstance(class_or_class_name, str):
        name_parts = class_or_class_name.split('.')
        module_name = '.'.join(
            name_parts[:-1]
        )
        target_class_name = name_parts[-1]

        # Raises ModuleNotFoundError if we can't resolve part of the module path
        target_module = importlib.import_module(module_name)

        target_class = getattr(target_module, target_class_name, None)
        if not target_class:
            raise ImportError("Class not found: '{}'.".format(class_or_class_name))

    if not inspect.isclass(target_class):
        raise TypeError(
            "'{}' is not a class.".format(class_or_class_name)
        )

    if compatible_class and not issubclass(target_class, compatible_class):
        raise ValueError(
            "Class '{}' does not derive from '{}.{}'.".format(
                class_or_class_name,
                compatible_class.__module__,
                compatible_class.__name__
            )
        )

    return target_class