import requests
import logging
from json import JSONDecodeError
from requests.exceptions import ConnectTimeout, RetryError

from common.third_party_api.exceptions import CallApiError

logger = logging.getLogger("")


class Configuration(object):
    def __init__(self, host, data, verify_ssl=False, proxy=None):
        self.host = host
        self.data = data
        self.verify_ssl = verify_ssl
        self.proxy = proxy


class APIClient(object):
    def __init__(self, configuration, timeout=5, retries=3):
        session = requests.Session()
        adapter = requests.adapters.HTTPAdapter(pool_connections=10,
                                                pool_maxsize=100,
                                                max_retries=retries)
        session.mount("http://", adapter)
        session.mount("https://", adapter)
        self.default_form_headers = {
            "User-Agent":
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 \
            (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
            "Accept": "*/*",
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
            "X-Requested-With": "XMLHttpRequest",
        }
        self.default_json_headers = {
            "User-Agent":
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 \
            (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
            "Accept": "*/*",
            "Content-Type": "application/json; charset=utf-8",
        }
        self.session = session
        self.login_url = "http://" + configuration.host + "/login"
        try:
            cookies_jar = requests.post(self.login_url,
                                        headers=self.default_form_headers,
                                        data=configuration.data).cookies
            self.session.cookies = cookies_jar
        except Exception:
            pass
        self.timeout = timeout
        self.configuration = configuration

    def refresh_token(self):
        cookies_jar = requests.post(self.login_url,
                                    headers=self.default_form_headers,
                                    data=configuration.data).cookies
        self.session.cookies = cookies_jar


class BaseClient(object):
    def __init__(self, apiclient):
        self.apiclient = apiclient
        self.client = apiclient.session

    def request(self, url, method, headers=None, body=None, *args, **kwargs):
        timer = kwargs.get("timer", 0)
        if not headers:
            headers = self.apiclient.default_json_headers
        final_url = "http://" + self.apiclient.configuration.host + url
        try:
            response = self.client.request(url=final_url,
                                           method=method,
                                           headers=headers)
        except ConnectTimeout as e:
            raise CallApiError("time out", e.response.status_code, url, method,
                               e.response)
        except RetryError as e:
            raise CallApiError("max retries", e.response.status_code, url,
                               method, e.response)
        if response.status_code == 401 and timer < 2:
            timer += 1
            self.apiclient.refresh_token()
            self.client = self.apiclient.session
            kwargs.update({"timer": timer})
            self.request(url,
                         method,
                         headers=headers,
                         body=body,
                         *args,
                         **kwargs)
        try:
            data = response.json()
            return data
        except JSONDecodeError as e:
            logger.debug(e)
            logger.debug(response.content)
            timer += 1
            self.apiclient.refresh_token()
            self.client = self.apiclient.session
            kwargs.update({"timer": timer})
            self.request(url,
                         method,
                         headers=headers,
                         body=body,
                         *args,
                         **kwargs)

    def get(self, url, headers=None, body=None, *args, **kwargs):
        return self.request(url,
                            method="GET",
                            headers=headers,
                            body=body,
                            *args,
                            **kwargs)

    def post(self, url, headers=None, body=None, *args, **kwargs):
        return self.request(url,
                            method="POST",
                            headers=headers,
                            body=body,
                            *args,
                            **kwargs)


form_data = {
    "username": 13818469856,
    "password": "6bc660af0e8025daa672c9b05929a286",
    "loginType": "ADMIN",
    "domain": "www.hcbgps.com",
}

configuration = Configuration(host="www.hcbgps.com", data=form_data)
