import urllib.parse
import logging
from functools import wraps
from unittest.mock import MagicMock
from oaa.modules.params_or_env import params_or_env
logger = logging.getLogger(__name__)


MOCK_RESPONSES = {}


class MockResponse:
    def __init__(self, resp, status_code=200):
        """TODO: Docstring for __init__.

        :resp: TODO
        :returns: TODO

        """
        self.response = resp
        self._status_code = status_code

    # @classmethod
    def json(self, *args):
        return self.response

    @property
    def status_code(self):
        # import bpdb; bpdb.set_trace()  # noqa: E702

        return self._status_code 


def mock_response(_func=None, path=None, status_code=200, **kwargs):

    def inner(func):

        @wraps(func)
        def wrapper(*args, **kwargs):
            """A wrapper function"""

            # Extend some capabilities of func
            res = MockResponse(func(*args, **kwargs), status_code=status_code)
            logger.debug('returning mocked response for %s -- %s', path, res)

            return res

        # do something before the decorator is returned
        # HOOK_EVENTS[event]['hooks'].append(wrapper)

        if not path:
            raise Exception(f'You must define an overrided path for mocks({path})')
        ret = None

        logger.debug('preparing mock response for %s', path)
        MOCK_RESPONSES[path] = wrapper

        return MOCK_RESPONSES[path]

    if _func is None:
        return inner

    return inner(_func)


class OAAMockException(Exception):
    pass


def call_response(path):
    """TODO: Docstring for call_response.

    :path: TODO
    :returns: TODO

    """

    if not MOCK_RESPONSES.get(path):
        raise OAAMockException(f'no overridden path provided for {path}')

    return MOCK_RESPONSES.get(path)()


def get_sideeffect(path, *args, **kwargs):
    try:
        path = urllib.parse.urlparse(path).path
    except Exception as e:
        print('path', path, e)
    logger.debug('getting response for %s', path)
    res = call_response(path)

    if res is None:
        raise OAAMockException(f'no mocked response for path {path}')

    return res


def maybe_mock_it(mocked_object, method, connection, source):

    if str(params_or_env(connection, source, 'MOCK_RESULTS')).lower() == 'true':
        setattr(mocked_object, method, MagicMock(side_effect=get_sideeffect))
