"""
Pinterest Client
"""
import os
from importlib import reload

from openapi_generated.pinterest_client.configuration import Configuration
from openapi_generated.pinterest_client.api_client import ApiClient
from pinterest import config
from pinterest.utils.refresh_access_token import get_new_access_token
from pinterest.utils.sdk_exceptions import SdkException


__all__ = ['default_sdk_client', 'PinterestSDKClient']

default_sdk_client = None


class PinterestSDKClient(ApiClient):
    # pylint: disable=too-many-arguments
    """
    Wrapper API client for SDK high level models

    NOTE: This class is base in a generated by OpenAPI Generator.
    Ref: https://openapi-generator.tech
    """

    def __init__(self, access_token=None, refresh_token=None, app_id=None, app_secret=None, configuration=None,
                 header_name=None, header_value=None, cookie=None, pool_threads=1):
        _configuration = None

        if access_token:
            _configuration = PinterestSDKClient._get_config(access_token)

        if (refresh_token and app_id and app_secret) and not access_token:
            _access_token = PinterestSDKClient._get_access_token(
                refresh_token,
                app_id,
                app_secret
            )
            _configuration = PinterestSDKClient._get_config(_access_token)

        if configuration:
            _configuration = configuration

        super().__init__(configuration=_configuration,
                         header_name=header_name,
                         header_value=header_value,
                         cookie=cookie,
                         pool_threads=pool_threads,
                         user_agent=config.PINTEREST_USER_AGENT)

    @classmethod
    def create_client_with_refresh_token(cls, refresh_token: str, app_id: str, app_secret: str):
        """Get a new SDK client with the given refresh token, app id and app secret."""
        access_token = cls._get_access_token(
            refresh_token=refresh_token,
            app_id=app_id,
            app_secret=app_secret
        )
        return PinterestSDKClient(
            configuration=cls._get_config(
                access_token=access_token
            )
        )

    @classmethod
    def create_client_with_token(cls, access_token: str):
        """Get a new SDK client with the given access token."""
        return PinterestSDKClient(
            configuration=cls._get_config(
                access_token=access_token
            )
        )

    @classmethod
    def set_default_client(cls, client):
        """Replace the default client with the given client."""
        global default_sdk_client  # pylint: disable=global-statement
        default_sdk_client = client

    @classmethod
    def set_default_access_token(cls, access_token: str):
        """Replace the default access_token with the given ones."""
        os.environ['PINTEREST_ACCESS_TOKEN'] = access_token
        cls._reset_default_client()
        reload(config)

    @classmethod
    def set_default_refresh_token(cls, refresh_token: str, app_id: str, app_secret: str):
        """Replace the default refresh_token, app_id, app_secret with the given ones."""
        os.environ['PINTEREST_REFRESH_ACCESS_TOKEN'] = refresh_token
        os.environ['PINTEREST_APP_ID'] = app_id
        os.environ['PINTEREST_APP_SECRET'] = app_secret
        cls._reset_default_client()
        reload(config)

    @classmethod
    def create_default_client(cls):
        """
        Returns the default SDK client.

        If client is not explicitly initialized, a new client will be initialized from environment variables.
        """
        if not default_sdk_client:
            cls._init_default_sdk_client_from_env()
        return default_sdk_client

    @classmethod
    def _init_default_sdk_client_from_env(cls):
        """Loads a new SDK client from environment variables."""
        if not config.PINTEREST_ACCESS_TOKEN and not config.PINTEREST_REFRESH_ACCESS_TOKEN:
            raise SdkException("Environment variables not present. \
                Kindly initialize required environment variables: [PINTEREST_ACCESS_TOKEN] or \
                    [PINTEREST_APP_ID, PINTEREST_APP_SECRET, PINTEREST_REFRESH_ACCESS_TOKEN]")

        access_token = config.PINTEREST_ACCESS_TOKEN
        if not access_token:
            access_token = cls._get_access_token()

        configuration = cls._get_config(access_token)
        cls._set_default_client(client=cls(configuration=configuration))


    @classmethod
    def _get_access_token(
            cls, app_id: str = config.PINTEREST_APP_ID,
            app_secret: str = config.PINTEREST_APP_SECRET,
            refresh_token: str = config.PINTEREST_REFRESH_ACCESS_TOKEN,
            api_uri: str = config.PINTEREST_API_URI
    ):
        return get_new_access_token(
            app_id=app_id,
            app_secret=app_secret,
            refresh_access_token=refresh_token,
            host=api_uri,
        )

    @classmethod
    def _get_config(cls, access_token: str,
                    api_uri: str = config.PINTEREST_API_URI,
                    debug: str = config.PINTEREST_DEBUG,
                    log_file: str = config.PINTEREST_LOG_FILE,
                    logger_format: str = config.PINTEREST_LOGGER_FORMAT,
                    disabled_client_side_validations: str = config.PINTEREST_DISABLED_CLIENT_SIDE_VALIDATIONS):
        _config = Configuration(
            access_token=access_token,
            host=api_uri,
        )

        _config.debug = debug
        _config.logger_file = log_file
        _config.logger_format = logger_format
        _config.disabled_client_side_validations = disabled_client_side_validations
        return _config

    @classmethod
    def _set_default_client(cls, client):
        global default_sdk_client  # pylint: disable=global-statement
        default_sdk_client = client

    @classmethod
    def _reset_default_client(cls):
        global default_sdk_client  # pylint: disable=global-statement
        default_sdk_client = None
