# coding=utf8

import json
import requests

from auto_keyworder_modules import util


def format_url(
    server: str,
    endpoint: str,
) -> str:
    while server.endswith('/'):
        server = server[:-1]
    while endpoint.startswith('/'):
        endpoint = endpoint[1:]
    return f'{server}/api/v1/{endpoint}'


def easydb_post(
    server: str,
    endpoint: str,
    params: dict = {},
    easydb_token: str = None,
    payload=None,
    timeout: int = 300,
) -> tuple[int, str]:
    if easydb_token is not None:
        params['token'] = easydb_token

    if isinstance(payload, list) or isinstance(payload, dict):
        payload = json.dumps(payload)

    url = format_url(server, endpoint)

    response = None
    try:
        response = requests.post(url, params=params, data=payload, timeout=timeout)
    except Exception as e:
        return None, str(e)

    try:
        return response.status_code, json.loads(response.content)
    except Exception as e:
        return response.status_code, response.content


def easydb_get(
    server: str,
    endpoint: str,
    params: dict = {},
    easydb_token: str = None,
    timeout: int = 300,
) -> tuple[int, str]:
    if easydb_token is not None:
        params['token'] = easydb_token

    url = format_url(server, endpoint)

    response = None
    try:
        response = requests.get(url, params=params, timeout=timeout)
    except Exception as e:
        return None, str(e)

    try:
        return response.status_code, json.loads(response.content)
    except Exception as e:
        return response.status_code, response.content


def easydb_authenticate(
    server: str,
    login: str,
    password: str,
) -> tuple[str, dict]:
    # get session token
    status_code, resp = easydb_get(server, 'session', timeout=30)

    if status_code != 200:
        return None, resp

    token = util.get_json_value(resp, 'token')
    if token is None:
        return None, resp

    # authenticate token
    status_code, resp = easydb_post(
        server,
        'session/authenticate',
        params={
            'method': 'easydb',
            'login': login,
            'password': password,
        },
        easydb_token=token,
        timeout=30,
    )

    if status_code != 200:
        return None, resp

    return token, resp


def easydb_search(
    server: str,
    easydb_token: str,
    query,
) -> tuple[int, str]:
    return easydb_post(
        server,
        'search',
        easydb_token=easydb_token,
        payload=query,
    )


def easydb_post_objects(
    server: str,
    easydb_token: str,
    objecttype: str,
    objects: list,
    format: str = None,
) -> tuple[int, str]:
    return easydb_post(
        server,
        f'db/{objecttype}',
        easydb_token=easydb_token,
        params={'format': format},
        payload=objects,
    )


def confirm_pending_tasks(
    server: str,
    easydb_token: str,
    auth_response: dict,
) -> tuple[str, str]:

    # check if any pending tasks must be confirmed
    pending_tasks = util.get_json_value(auth_response, 'pending_tasks')
    if not isinstance(pending_tasks, list):
        return None, None
    if len(pending_tasks) < 1:
        return None, None

    # confirm all pending tasks
    message_keys = set()
    for task in pending_tasks:
        message_key = util.get_json_value(task, 'message.message_key')
        if message_key is None:
            continue
        message_keys.add(message_key)

    if len(message_keys) < 1:
        return None, None

    status_code, resp = easydb_post(
        server,
        'session/messages_confirm',
        payload=list(message_keys),
        easydb_token=easydb_token,
        timeout=30,
    )

    if status_code != 200:
        return None, resp

    return resp, None
