import logging
import click


def coerce(provided: str, field: str, spec: dict):
    """
    Attempts to coerce the provided condition to the expected field value for better filtering/sorting comparisons.

    Supported types are `bool`, `int` and `float`.

    :param provided: value to coerce
    :param field: required field
    :param spec: specification of `field->field-type` mapping
    :return: the coerced value or the original value (if coercion failed)
    """
    expected = spec.get(field, None)

    if expected == bool:
        provided = provided.lower()
        if provided == 'true':
            return True
        elif provided == 'false':
            return False
        else:
            logging.error('Cannot convert [{}] to boolean'.format(provided))
        raise click.Abort()
    elif expected == int:
        return int(provided)
    elif expected == float:
        return float(provided)
    elif expected == str:
        return str(provided)
    else:
        logging.error('Unsupported type encountered for expected value: [{}]'.format(type(expected)))
        raise click.Abort()