# coding=utf8

import sys
import traceback
import json

from datetime import timedelta, timezone, datetime

from auto_keyworder_modules.ai_services import ai_service_configuration


def __log(logger, log_level: str, message: str) -> None:
    if not logger:
        # xxx
        print(f'[{log_level}] {message}')
        return

    if log_level == "debug":
        logger.debug(message)
        return

    if log_level == "info":
        logger.info(message)
        return

    if log_level == "warn":
        logger.warn(message)
        return

    if log_level == "error":
        logger.error(message)
        return


def log_debug(logger, message: str) -> None:
    __log(logger, "debug", message)


def log_info(logger, message: str) -> None:
    __log(logger, "info", message)


def log_warn(logger, message: str) -> None:
    __log(logger, "warn", message)


def log_error(logger, message: str) -> None:
    __log(logger, "error", message)


# -----------------------------------

DATETIME_FORMAT = '%Y-%m-%dT%TZ'


def format_datetime(d):
    return d.strftime(DATETIME_FORMAT)


def dumpjs(js, ind=4):
    return json.dumps(js, indent=ind)


def get_json_value(js, path, expected=False):
    current = js
    path_parts = path.split('.')
    for path_part in path_parts:
        if not isinstance(current, dict) or path_part not in current:
            if expected:
                raise Exception('internal', f'expected: {path_part}')
            else:
                return None
        current = current[path_part]
    return current


def print_response(resp):
    if isinstance(resp, dict):
        return dumpjs(resp)
    if isinstance(resp, list):
        return dumpjs(resp)
    return str(resp)


def print_traceback(logger, e, _raise=False):
    exc_info = sys.exc_info()
    stack = traceback.extract_stack()
    tb = traceback.extract_tb(exc_info[2])
    full_tb = stack[:-1] + tb
    exc_line = traceback.format_exception_only(*exc_info[:2])
    traceback_array = [
        f'Exception: {repr(e)}',
        traceback.format_list(full_tb) + exc_line,
    ]
    log_debug(logger, f'{traceback_array[0]}\n{"".join(traceback_array[1])}')
    if _raise:
        raise e

    return traceback_array


def now() -> datetime:
    return datetime.now(timezone.utc)


def get_next_run(hour: int, days_pause: int = 0):
    _now = now()
    _next = _now.replace(
        hour=hour,
        minute=0,
        second=0,
        microsecond=0,
        tzinfo=_now.tzinfo,
    )
    if _now >= _next:
        _next = _next + timedelta(days=1 + days_pause)
    return _next


def parse_base_config(config_name: str, auto_keyworder_config: dict) -> list:
    service_configs = auto_keyworder_config.get(config_name)
    if not service_configs:
        return []

    if not isinstance(service_configs, list):
        return []

    configs = []
    for config_element in service_configs:

        if config_name == "configs_cloudsight":
            _config = ai_service_configuration.CloudsightConfiguration()

        elif config_name == "configs_deepva":
            _config = ai_service_configuration.DeepvaConfiguration()

        elif config_name == "configs_imagga":
            _config = ai_service_configuration.ImaggaConfiguration()

        else:
            continue

        if not _config.parse_base_config_element(
            shared_config=auto_keyworder_config,
            specific_config=config_element,
        ):
            continue
        _config.parse_specific_variables(config_element)

        configs.append(_config)

    return configs
