import functools
from .http import Response
from .exceptions import (
    ServerError,
    AuthenticationError,
    AuthorizationError,
    ClientError,
    MaxRetryError,
)


def error_response(exc: Exception) -> Response:
    """
    Modify or create a response object with the error message,
    exception and status code information added.
    """

    status = 400
    msg = 'Request Error'
    if isinstance(exc, AuthenticationError):
        status = 401
        msg = 'Authorization Error'
    if isinstance(exc, AuthorizationError):
        status = 403
        msg = 'Authorization Error'
    elif isinstance(exc, ServerError):
        status = 500
        msg = 'Remote Server Error'
    elif isinstance(exc, ClientError):
        msg = 'Local Client Error'
    elif isinstance(exc, MaxRetryError):
        msg = 'Cannot Connect to Server Error'

    if hasattr(exc, 'response'):
        resp = exc.response
    else:
        resp = Response(
            body=str(exc),
            status=status,
        )

    if not hasattr(resp, 'status'):
        resp.status = resp.status_code

    resp.custom_msg = msg
    resp.exception = exc

    return resp


def exception_response(function):  # type: ignore[no-untyped-def]
    """
    A decorator that returns the function value
    or a Response-like object containing
    details of the error that occurred.
    """

    @functools.wraps(function)
    def wrapper(*args, **kwargs):  # type: ignore[no-untyped-def]
        try:
            return function(*args, **kwargs)
        except Exception as e:
            return error_response(exc=e)  # noqa

    return wrapper


__all__ = (
    'error_response',
    'exception_response',
)
