"""
    CLASS API LOADER to S3 Directory
    https://www.amocrm.com/developers/content/api_v4/leads-2/
"""

import logging
from abc import ABC

from amocrm.api.base.api_loader_base import AmocrmApiLoaderBase

PAGE_NUMBER_MAX = 1e6


def get_limit_from_url(objects):
    """
    get page limit form response
    :param objects:
    :return:
    """
    import urllib.parse as urlparse

    url = objects.json()["_links"]["self"]["href"]
    par = urlparse.parse_qs(urlparse.urlparse(url).query)
    return int(par["limit"][0])


def process_json(data, entity):
    """
    update data after retrieving from s3
    Args:
        data: row data json
    Returns: list
    """
    return data["_embedded"][entity]


class AmocrmApiLoader(AmocrmApiLoaderBase, ABC):
    """
    The main class
    """

    def __init__(
        self,
        entity,
        s3_client,
        args_api,
        date_modified_from=None,
        batch_api=250,
        is_oauth2=True,
    ):
        """
        :param entity:   amocrm entities contacts/users/accounts e.t.c
        :param s3_client: s3 client from talenttech-oss library
        :param args_api: dict with AMO_USER_LOGIN/AMO_USER_HASH/AMO_AUTH_URL
        :param date_modified_from:
        :param batch_api: size of batch to upload
        """

        AmocrmApiLoaderBase.__init__(
            self,
            entity=entity,
            s3_client=s3_client,
            args_api=args_api,
            date_modified_from=date_modified_from,
            batch_api=batch_api,
            is_oauth2=is_oauth2,
        )

        self.logger = logging.getLogger(__class__.__name__)

    def extract(self):
        """load table from amocrm.api"""
        self.auth()
        self.create_s3_folder()
        self.clear_s3_folder()  # clear old before loading

        url_base = self.args_api["amocrm_api_url"]
        cur_page = 1

        params = {}
        if self.date_modified_from is not None:
            self.logger.info("Uploading data with after %s ", self.date_modified_from)
            params["filter[updated_at][from]"] = int(
                self.date_modified_from.timestamp()
            )
        has_next = True
        while has_next and cur_page < PAGE_NUMBER_MAX:
            self.logger.info("Extracting page №%d", cur_page)
            file_path = self.get_file_name(cur_page, self.batch_api)

            url = url_base.format(limit=self.batch_api, page=cur_page)

            objects = self.oath_client.get_response_objects(url, params)

            self.logger.info(objects.url)
            if objects.status_code != 200:
                self.logger.warning(
                    "Warning! API sent no result %d", objects.status_code
                )
                return

            limit_from_url = get_limit_from_url(objects)
            if "next" not in objects.json()["_links"]:
                has_next = False

            if limit_from_url != self.batch_api:
                logging.warning(
                    "Batch API: %d is too large, changing to default value %d",
                    self.batch_api,
                    limit_from_url,
                )
                self.batch_api = limit_from_url

            count_uploaded = len(process_json(objects.json(), self.entity))
            self.rows_to_upload += count_uploaded
            self.logger.info(
                "Saving data in the file %s, a number of rows %d, total number: %d",
                file_path,
                count_uploaded,
                self.rows_to_upload,
            )
            self.s3_client.create_file(file_path, objects.content)
            if count_uploaded < self.batch_api:
                logging.warning(
                    "A number of rows %d in response less then size of batch %d. Make a return",
                    count_uploaded,
                    self.batch_api,
                )
                return

            cur_page += 1
        self.logger.info(
            "Total number of rows received from API is %d", self.rows_to_upload
        )
