# This file is used to import the correct query module:
# onetick.query or onetick.query_webapi
# based on the environment variable OTP_WEBAPI
# Re-use this file in your tests to import the correct onetick.query module
# Also it is override pyomd and OneTickLib classes with mock classes

import getpass
import inspect
import os
import tempfile
import warnings
import onetick.py as otp
from onetick.py import configuration


class OneTickLib:
    # mock class for OneTickLib, used for webapi and onetick-query-stubs
    # maybe it is not right to combine this namesake classes (onetick.lib.OneTickLib and pyomd.OneTickLib)
    # but it is done to simplify the code and it is not affecting anything except tests
    LOGGING_LEVEL_MIN = 0
    LOGGING_LEVEL_LOW = 1
    LOGGING_LEVEL_MEDIUM = 2
    LOGGING_LEVEL_MAX = 3
    set_authentication_token = None

    def __init__(self, *args, **kwargs):  # NOSONAR
        pass

    def set_log_file(self, log_file):  # NOSONAR
        pass

    def cleanup(self):  # NOSONAR
        pass


if os.getenv("OTP_SKIP_OTQ_VALIDATION", False):
    import onetick_stubs as otq  # noqa: F401
    import pyomd  # noqa: F401

    class ConfigStub:
        API_CONFIG: dict = {}

    class otli:
        OneTickLib = OneTickLib  # NOSONAR

    for key, value in otq.query.__dict__.items():
        setattr(otq, key, value)
    setattr(otq, 'webapi', False)
    setattr(otq, 'config', ConfigStub)
    setattr(otq, 'graph_components', otq)

elif otp.__webapi__:
    import onetick.query_webapi as otq  # noqa: F401
    setattr(otq, 'webapi', True)

    from onetick.py.pyomd_mock import pyomd

    __original_run = otq.run

    def run(*args, **kwargs):
        from onetick.py import config  # noqa
        from onetick.py.compatibility import is_max_concurrency_with_webapi_supported

        if not config.http_address and 'http_address' not in kwargs:
            raise ValueError('otp.run() http_address keyword param, '
                             'otp.config.http_address or OTP_HTTP_ADDRESS '
                             'environment variable are required '
                             'when using WebAPI mode.')

        # TODO WEBAPI review this
        # if file name is not in single quotes, then put it in single quotes
        query_name = None
        query = kwargs.get('query', None)
        if isinstance(query, str):
            if query[0] == "'" and query[-1] == "'":
                query = query.replace("'", "")
            if '::' in query:
                query_name = query.split('::')[-1]
                query = query.replace(f'::{query_name}', '')
            kwargs['query'] = query
        kwargs['query_name'] = query_name

        del_params = [
            'start_time_expression',
            'end_time_expression',
            'alternative_username',
            'batch_size',
            'treat_byte_arrays_as_strings',
            'output_matrix_per_field',
            'return_utc_times',
            'connection',
            'svg_path',
            'use_connection_pool',
            'time_as_nsec',
            'max_expected_ticks_per_symbol',
        ]
        ignore_deleted_params = [
            'treat_byte_arrays_as_strings',
            'time_as_nsec',
            'alternative_username',
            'max_expected_ticks_per_symbol'
        ]
        for param in del_params:
            if param in kwargs:
                if kwargs[param] and param not in ignore_deleted_params:
                    warnings.warn(f'Parameter {param} is not supported in WebAPI mode and will be ignored.')
                del kwargs[param]

        from onetick.py import config  # noqa
        if 'http_address' not in kwargs:
            kwargs['http_address'] = config.http_address

        if kwargs.get('username'):
            kwargs['http_username'] = kwargs['username']
            del kwargs['username']
        else:
            kwargs['http_username'] = config.http_username

        if kwargs.get('password'):
            kwargs['http_password'] = kwargs['password']
            del kwargs['password']
        else:
            kwargs['http_password'] = config.http_password

        if 'access_token' not in kwargs:
            if config.access_token:
                kwargs['access_token'] = config.access_token
        elif not kwargs['access_token']:
            del kwargs['access_token']

        access_token_url = kwargs.get('access_token_url', config.access_token_url)
        if access_token_url:
            if not hasattr(otq, 'get_access_token'):
                raise RuntimeError('Current `onetick.query_webapi` version doesn\'t have `get_access_token` function')

            if kwargs.get('access_token'):
                raise ValueError('Both `access_token` and `access_token_url` set, instead of only one of them.')

            if 'client_id' in kwargs:
                client_id = kwargs.pop('client_id')
            else:
                client_id = config.client_id

            if 'client_secret' in kwargs:
                client_secret = kwargs.pop('client_secret')
            else:
                client_secret = config.client_secret

            for param_name, param_value in zip(['client_id', 'client_secret'], [client_id, client_secret]):
                if not param_value:
                    raise ValueError(f'`access_token_url` parameter set, however `{param_name}` parameter missing.')

            kwargs['access_token'] = otq.get_access_token(access_token_url, client_id, client_secret)

            if 'access_token_url' in kwargs:
                del kwargs['access_token_url']

        if 'http_proxy' not in kwargs:
            kwargs['http_proxy'] = config.http_proxy

        if 'https_proxy' not in kwargs:
            kwargs['https_proxy'] = config.https_proxy

        is_trusted_certificates_supported = 'trusted_certificates_file' in inspect.signature(otq.run).parameters

        if (
            ('trusted_certificates_file' in kwargs or config.trusted_certificates_file is not None) and
            not is_trusted_certificates_supported
        ):
            raise ValueError(
                'Parameter `trusted_certificates_file` was set, however current version of OneTick doesn\'t support it.'
            )

        if 'trusted_certificates_file' not in kwargs and is_trusted_certificates_supported:
            kwargs['trusted_certificates_file'] = config.trusted_certificates_file

        if 'callback' in kwargs and kwargs['callback'] is not None:
            kwargs['output_mode'] = otq.QueryOutputMode.callback

        if 'max_concurrency' in kwargs and not is_max_concurrency_with_webapi_supported():
            kwargs['max_concurrency'] = None

        return __original_run(*args, **kwargs)

    otq.run = run

    otq.OneTickLib = OneTickLib

    class otli:  # type: ignore # noqa: F401
        OneTickLib = otq.OneTickLib  # NOSONAR

else:
    import onetick.query as otq  # type: ignore # noqa: F401
    import pyomd  # type: ignore # noqa: F401
    import onetick.lib.instance as otli  # type: ignore # noqa: F401
    setattr(otq, 'webapi', False)


def _tmp_otq_path():
    # copied from onetick.test.fixtures _keep_generated_dir() with replacement to /tmp
    # required with OTP_WEBAPI_TEST_MODE to separate otq files from shared dbs+config+locator+acl files
    from onetick.py import utils  # noqa
    res = os.path.join(utils.TMP_CONFIGS_DIR(), os.environ.get("ONE_TICK_TMP_DIR", "otqs"))
    res = res.replace(utils.temp.WEBAPI_TEST_MODE_SHARED_CONFIG,
                      os.path.join(tempfile.gettempdir(), "test_" + getpass.getuser()))

    # % and + is some webapi related path bugs, probably would be fixed someday
    return res.replace("%", "_").replace("+", "_")


__all__ = ['otq', 'pyomd', 'otli', '_tmp_otq_path']
