from typing import Dict
from typing import Tuple
from typing import Union


def validate_input(in_data: dict,  # TESTED
                   expected: Dict[str, type]) -> Tuple[Union[str, bool], int]:
    """Determines if the data given is a dictionary, if the key exsists in
    the input, and if the value in the key matches the type that was expected.

    An expectation of the type of data in each key is established
    and fed into this function along with a dictionary data set.
    The Validate input funx then checks if the input was a dictionary(if not,
    return string and 400 error), if the key specified is missing(if missing
    return string and 400 error), and if the data type of each key is correct
    (if not return str and 400).

    :param in_data: dictionary of data
    :param expected: dictionary data key types expectations (tuple)

    :return: String and 400 error (not dictionary, or wrong dictionary value
     type) or True + 200 code.
    :rtype: Tuple[Union[str, bool], int]

    """
    if not isinstance(in_data, dict):
        return "The input was not a dictionary.", 400
    for key, value in expected.items():
        if key not in in_data.keys():
            continue
        elif not isinstance(in_data[key], value):
            return "the key '{}' is a {}, should be {}".format(
                key, type(in_data[key]), expected[key]), 400
    return True, 200