import json
from functools import wraps
from urllib.parse import parse_qs

import typing
from aws_lambda_tools.common import openapi_json_serde
from aws_lambda_tools.common.response import Response, ResponseMimeType
from pycomb.exceptions import PyCombValidationError

from conio_sdk.logging.factory import LOGGING_FACTORY


def x_www_form_urlencoded(
        message_type: typing.Optional[typing.Type] = None,
        combinator: typing.Optional[typing.Callable[[object], object]] = None):
    def x_www_form_fun_decorator(fun):
        @wraps(fun)
        def wrapper(event, context, bin_data=b''):
            LOGGING_FACTORY.test.info('TEST 1')
            if message_type:
                LOGGING_FACTORY.test.info('TEST 2 %s', bin_data)
                data = openapi_json_serde.deserialize({k: v[0] for k, v in parse_qs(bin_data).items()}, message_type)
            else:
                LOGGING_FACTORY.test.info('TEST 2.1 %s', bin_data)
                data = {k: v[0] for k, v in parse_qs(bin_data).items()} if bin_data else None
            LOGGING_FACTORY.test.info('TEST 3 %s', data)
            if combinator:
                try:
                    combinator(data)
                except PyCombValidationError as e:
                    # _logger_validation.debug('Offending message: %s', data)
                    # _logger_validation.warning('Validation error: %s', e, exc_info=True)
                    return Response(status_code=400)
            LOGGING_FACTORY.test.info('TEST 4 %s', data)
            result = fun(data, event, context)
            LOGGING_FACTORY.test.info('TEST 5 %s', result)
            if isinstance(result, Response):
                LOGGING_FACTORY.test.info('TEST 6 %s', result)
                return result
            else:
                LOGGING_FACTORY.test.info('TEST 6.1 %s', result)
                # _logger_request.info('Response message %s: %s', type(result), result)
                return Response(
                    content=json.dumps(result) if isinstance(result, dict) else openapi_json_serde.serialize(result),
                    content_type=ResponseMimeType.JSON
                )
        return wrapper
    return x_www_form_fun_decorator
