# Copyright (c) 2022 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 functools
import pyfaaster.aws.handlers_decorators_v2 as faaster
from aws_lambda_powertools import Logger, Tracer
from voluptuous import Schema, REMOVE_EXTRA, Invalid
from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEvent

from czc import json
from czc.api.adapters.response import http_response
from czc.authorization import organization_path_authorizer
from czc.api.v2.testing import web_test_key_aware
from czc.api.v2.exceptions import BadRequestError

logger = Logger()
tracer = Tracer()


def web_api(default_error_message: str = None,
            path_schema: dict = None,
            query_schema: Schema = None,
            multi_value_query_schema: Schema = None,
            body_schema: Schema = None):
    def _internal_api_handler(handler):
        @web_test_key_aware()
        @http_response(default_error_message)
        @faaster.allow_origin_response(r'^https://.*\.cloudzero\.com$')
        @organization_path_authorizer
        @functools.wraps(handler)
        def handler_wrapper(event, context, **kwargs):
            valid_path_schema = Schema({'organizationId': str}, required=True).extend(path_schema or {})
            valid_query_schema = query_schema or Schema({}, extra=REMOVE_EXTRA)
            valid_mvq_schema = multi_value_query_schema or Schema({}, extra=REMOVE_EXTRA)
            gateway_event = APIGatewayProxyEvent(event)
            try:
                path_params = valid_path_schema(gateway_event.path_parameters or {})
                query_params = valid_query_schema(gateway_event.query_string_parameters or {})
                mvq_params = valid_mvq_schema(gateway_event.multi_value_query_string_parameters or {})
                body_param = dict(body=body_schema(json.loads(gateway_event.body))) if body_schema else {}
            except Invalid as e:
                logger.exception(e)
                raise BadRequestError('Failed to validate parameters', invalid_exception=e)
            result = handler(event, context, **path_params, **query_params, **mvq_params, **body_param, **kwargs)
            return {
                'body': result
            }

        return handler_wrapper

    return _internal_api_handler
