import logging

from cubicweb import AuthenticationError, Forbidden, Unauthorized, QueryError
from pyramid.config import Configurator
from pyramid.request import Request
from rql import RQLException
from yams import ValidationError, UnknownType

from cubicweb_api.httperrors import get_http_error, get_http_500_error

log = logging.getLogger(__name__)


class ApiException(Exception):
    def __init__(self, original_exception):
        self.original_exception = original_exception


def api_exception_vue(exc: ApiException, request: Request):
    log.info(exc.__class__.__name__, exc_info=True)
    if isinstance(exc.original_exception, ValidationError):
        exc.original_exception.translate(request.cw_cnx._)
    log.info(exc.__class__.__name__, exc_info=True)
    # RQL errors -> 400
    if isinstance(
        exc.original_exception, (ValidationError, QueryError, UnknownType, RQLException)
    ):
        return get_http_error(400, exc.__class__.__name__, str(exc))
    # Authentication and Unauthorized -> 401
    if isinstance(exc.original_exception, (AuthenticationError, Unauthorized)):
        return get_http_error(401, exc.__class__.__name__, str(exc))
    # Forbidden -> 403
    if isinstance(exc.original_exception, Forbidden):
        return get_http_error(403, exc.__class__.__name__, str(exc))
    # Default case -> 500
    return get_http_500_error()


def includeme(config: Configurator):
    config.add_exception_view(api_exception_vue, context=ApiException)