import json

import requests
from application.model import UpdateType
from application.model.configuration import Configurations
from application.model.customexception import ErrorRetrievingPendingUpdate
from helper import retry, json_serialize
from requests import Response
from application.util import LoggerUtil, settings, ErrorResponseUtil
from typing import Dict, List

NONE_RESPONSE_ERROR = "Could not obtain the request response content"
logger = LoggerUtil.get_logger_name(__name__)


class MediaUpdaterAPIRepository(object):
    def __init__(self, configs):
        # type: (Configurations) -> None

        self.logger = logger
        self.configs = configs
        self.update_type = UpdateType.media
        self.local_configs = configs.updaters[self.update_type.name]
        self.response_util = ErrorResponseUtil()
        self.error_response = None

    def get_images_permissions(self, hashes_to_get_permission):
        # type: (List[str]) -> Dict

        self.logger.info("Obtaining images permissions...")
        settings.set_update_control("catalog", "$DOWNLOAD_IMAGES_AND_CATEGORY")
        url = self._get_download_image_permission_url()
        headers = self._get_app_json_headers()
        data = "{\"images_hashes\":" + json_serialize(hashes_to_get_permission) + "}"

        self.logger.info("Trying get image permissions for: {}".format(data))

        error_message = "Error getting images permissions: {}"
        response = retry(
            logger=self.logger,
            method_name="get_images_permissions",
            n=3,
            sleep_seconds=5,
            trying_to_do=lambda: requests.request("POST", url=url, headers=headers, data=data, timeout=60),
            is_success=lambda resp: resp.status_code == 200,
            success=lambda resp: resp,
            failed=lambda resp: self.logger.error(error_message.format(json_serialize(resp)))
        )

        if response is None:
            raise ErrorRetrievingPendingUpdate(NONE_RESPONSE_ERROR)

        self.logger.info("Permissions obtained!")
        return json.loads(response.content)

    def get_totem_config(self):
        # type: () -> Dict

        self.logger.info("Obtaining images totem...")
        url = self._get_download_image_totem_url()
        headers = self._get_app_json_headers()

        error_message = "Error getting totem config : {}"
        response = retry(
            logger=self.logger,
            method_name="get_images_totem",
            n=3,
            sleep_seconds=5,
            trying_to_do=lambda: requests.request("GET", url=url, headers=headers, timeout=60),
            is_success=lambda resp: resp.status_code == 200,
            success=lambda resp: resp,
            failed=lambda resp: self.logger.error(error_message.format(json_serialize(resp)))
        )

        if response is None:
            raise ErrorRetrievingPendingUpdate(NONE_RESPONSE_ERROR)

        self.logger.info("Permissions obtained!")
        return json.loads(response.content)

    @staticmethod
    def download_image(download_url):
        # type: (str) -> Response

        return requests.get(download_url, allow_redirects=True)

    def _get_app_json_headers(self):
        # type: () -> Dict[str, str]

        return {"X-Api-Key": self.configs.api_key,
                "Content-type": "application/json"}

    def _get_download_image_permission_url(self):
        # type: () -> str

        end_point_url = self.local_configs.endpoints.get_download_image_permission.format(storeId=self.configs.store_id)
        return self.configs.base_url + end_point_url

    def _get_download_image_totem_url(self):
        # type: () -> str

        end_point_url = self.local_configs.endpoints.get_download_image_totem.format(storeId=self.configs.store_id)
        return self.configs.base_url + end_point_url
