# This file typically contains the fetch function used for custom connectors

from oaa.modules.params_or_env import params_or_env
from oaa.modules.base_url_session import BaseURLSession
from oaa.hooks.mock_responses import maybe_mock_it
from oaa.hooks.decorators import hook, OAAHookEvent
from oaaclient.templates import OAAPermission
from oaa.utils import simple_jinja_render
import petl
from dotenv import load_dotenv
import logging
import urllib3

# from oaa.hooks.decorators import hook, OAAHookEvent

# During development against a local api, you may not have https properly configured
# use the below line to disable warnings about this
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# For easy debugging use the following line to act as a breakpoint
# import bpdb; bpdb.set_trace() # TODO: Remove this

load_dotenv()
CONFIG = {}
logger = logging.getLogger(__name__)

class {{app_name}}API:

    """Docstring for {{app_name}}API """

    def __init__(self, connection, source):
        """TODO: to be defined1.

        :connection: TODO
        :source: TODO

        """
        self._connection = connection
        self._source = source
        self.base_url = params_or_env(self._connection, 
                                      self._source, 
                                      '{{app_name.upper()}}_API_BASE_URL')
        self.api_key = params_or_env(self._connection,
                                     self._source,
                                     '{{app_name.upper()}}_API_API_TOKEN')
        self._session = None

    @property
    def session(self):
        if not self._session:
            self._session = BaseURLSession(self.base_url)
            self._session.headers.update(self.headers())

        return self._session

    def mkpath(self, path):
        return f'{self.base_url}{path}'

    def headers(self):
        header_dict = {
            'Authorization': f'Bearer {{self.api_key}}',
        }

        return header_dict

    def get(self, path, params=None, **kwargs):
        # self.session

        # Status: 429 means raite limit exhausted. Try again after x seconds
        res = self.session.get(path, params=params)

        if res.status_code == 429:
            # make this more rubust, exponential backoff
            time.sleep(5)

            return self.get(path, params=params, **kwargs)

        return res

    def get_next(self, res_json, source_params):
        _next = None

        if source_params:
            if source_params.get('pagination', 'links_next') == 'links_next':
                _next = res_json.get('links', {}).get('next')

            if source_params.get('pagination', '@nextLink') == '@nextLink':
                _next = res_json.get('@nextLink')

        return _next

    def fetch_paginated(self, path,
                        resource_key='',
                        query={},
                        _next=None,
                        source_params=None,
                        **kwargs):

        if _next:
            res = self.get(_next)
        else:
            res = self.get(path)

        if not res:
            logger.debug('path: %s', path)
            logger.error('res: %s', res)

            raise Exception(f'{resource} - {res}')
        res_json = res.json()

        yield from res_json.get(resource_key, [])

        _next = self.get_next(res_json, source_params)

        if _next:
            logger.info('fetching more results %s', _next)

            yield from self.fetch_paginated(path,
                                            resource_key=resource_key,
                                            query=query,
                                            _next=_next, **kwargs)



# ------------- the custom module fetch function

def get_api_obj(connection=None, source=None):
    if not CONFIG.get('{{app_name}}'):
        CONFIG['{{app_name}}'] = {{app_name}}API(connection, source)
    return CONFIG['{{app_name}}']

def fetch(connection=None, source=None, **kwargs):
    '''
    Fetch the data. This is the function that is called by oaa.

    '''

    load_dotenv()

    api = {{app_name}}API(connection, source)
    api = get_api_obj(connection=connection, source=source)

    maybe_mock_it(api, 'get', connection, source)

    resource_path = simple_jinja_render(source.params.get('resource', ''),
                                        {'connection': connection,
                                         'source': source})
    # f'/admin/v1/organizations/{connection.params.org_id}/orgReportUsers/'
    res = api.fetch_paginated(resource_path, 
                              resource_key=source.params.get('resource_key','data'))

    return petl.fromdicts(res)
