# Copyright (c) CloudZero - ALL RIGHTS RESERVED - PROPRIETARY AND CONFIDENTIAL
# Unauthorized copying of this file and/or project, via any medium is strictly prohibited.
# Direct all questions to legal@cloudzero.com

import base64
import gzip

from czc import json
from czc.logging import LogContext, Logger

DEFAULT_ERROR_MESSAGE = 'API Error'


def http_response(logger: Logger):
    """Make this Lambda Handler handle legacy response dictionaries and
    Pyfaaster Exceptions and API V2 ServiceErrors. This is a drop in replacement
    for pyfaaster.aws.handlers_decorators_v2.http_response.

    Parameters
    ----------

    Returns
    -------
    Callable
        Decorated Lambda Handler
    """

    def http_response_handler(handler):
        def handler_wrapper(event, context, **kwargs):
            try:
                with LogContext(logger=logger, method=event.get('httpMethod'), path=event.get('path')):
                    response: dict = handler(event, context, **kwargs)

                status_code = response.get('statusCode', 200)
                if status_code < 300:
                    return response

                if response.get('isBase64Encoded', False):
                    try:
                        encoded_error = base64.b64decode(response['body'])
                        error = gzip.decompress(encoded_error).decode()
                    except Exception:
                        logger.exception('Failed to decompress error body.')
                        error = DEFAULT_ERROR_MESSAGE
                else:
                    error = response.get('body', 'API Error')
                if status_code >= 500:
                    logger.error(error)
                elif status_code >= 300:
                    logger.warning(error)
                return response
            except Exception as err:
                status_code = getattr(err, 'status_code', getattr(err, 'statusCode', 500))
                error = getattr(err, 'body', DEFAULT_ERROR_MESSAGE)
                body = {'error': error['error'] if isinstance(error, dict) and 'error' in error else error}

                if status_code >= 500:
                    logger.exception(err)
                else:
                    logger.warning(err)

                return {'statusCode': status_code, 'body': json.dumps(body)}

        return handler_wrapper

    return http_response_handler
