import base64
import hashlib
import os
import random
from typing import Any

import requests
from pyramda import map, keys

from rabbitmqbaselibrary.common.exceptions import NotValidPermissions, NotFoundException
from rabbitmqbaselibrary.common.handlers import handle_rest_response_with_body, handle_rest_response

AUTOGENERATED = True

# noinspection SpellCheckingInspection
pass_chars = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!;#$%^&*-+<>|?"
salt = os.urandom(4)


def autogenerate_password() -> str:
    return "".join(random.sample(pass_chars, 10))


# noinspection InsecureHash
def salt_hashing_passwd(passwd: str) -> str:
    tmp0 = salt + passwd.encode('utf-8')
    tmp1 = hashlib.sha256(tmp0).digest()
    return str(base64.b64encode(salt + tmp1).decode(encoding='UTF-8'))


def is_present(broker: dict, name: str) -> bool:
    try:
        result = get_user_by_name(broker=broker, name=name)
        return True if result.get('name') == name else False
    except NotFoundException:
        return False


def get_user_by_name(broker: dict, name: str) -> dict:
    url = 'https://{}/api/users/{}'.format(broker['host'], name)
    response = requests.get(url=url, auth=(broker['user'], broker['passwd']))
    handle_rest_response(response=response, url=url)
    return response.json()


def get_users(broker: dict) -> dict:
    url = 'https://{}/api/users'.format(broker['host'])
    response = requests.get(url=url, auth=(broker['user'], broker['passwd']))
    handle_rest_response(response=response, url=url)
    return map(lambda i: i['name'], response.json())


def create_user(broker: dict, name: str, pass_flag: bool, **kwargs: Any) -> str:
    passwd: str = autogenerate_password() if pass_flag is True else str(kwargs.get('password'))
    hashed_passwd = salt_hashing_passwd(passwd=passwd)
    url = 'https://{}/api/users/{}'.format(broker['host'], name)
    tags = '' if kwargs.get('tags') is None else kwargs.get('tags')
    body = {'password_hash': hashed_passwd, 'tags': tags}
    response = requests.put(url=url, auth=(broker['user'], broker['passwd']), json=body)
    handle_rest_response_with_body(response=response, url=url, body=body)
    return passwd


def delete_user(broker: dict, name: str) -> None:
    url = 'https://{}/api/users/{}'.format(broker['host'], name)
    response = requests.delete(url=url, auth=(broker['user'], broker['passwd']))
    handle_rest_response(response=response, url=url)


def add_permissions(broker: dict, vhost: str, user: str, permissions: dict) -> None:
    kk = keys(permissions)
    if not ('write' in kk and 'read' in kk and 'configure' in kk):
        raise NotValidPermissions('permissions are not complete', permissions)
    url = 'https://{}/api/permissions/{}/{}'.format(broker['host'], vhost, user)
    response = requests.put(url=url, auth=(broker['user'], broker['passwd']), json=permissions)
    handle_rest_response_with_body(response=response, url=url, body=permissions)


def delete_permissions(broker: dict, vhost: str, user: str) -> None:
    url = 'https://{}/api/permissions/{}/{}'.format(broker['host'], vhost, user)
    response = requests.delete(url=url, auth=(broker['user'], broker['passwd']))
    handle_rest_response(response=response, url=url)


def get_permissions(broker: dict, vhost: str, user: str) -> dict:
    url = 'https://{}/api/permissions/{}/{}'.format(broker['host'], vhost, user)
    response = requests.get(url=url, auth=(broker['user'], broker['passwd']))
    handle_rest_response(response=response, url=url)
    return response.json()
