from rhodecode.lib.str_utils import safe_bytes
from rhodecode.lib.encrypt import encrypt_data, validate_and_decrypt_data
from rhodecode.lib.encrypt2 import Encryptor

ALLOWED_ALGOS = ['aes', 'fernet']


def get_default_algo():
    import rhodecode
    return rhodecode.CONFIG.get('rhodecode.encrypted_values.algorithm') or 'aes'


def encrypt_value(value: bytes, enc_key: bytes, algo: str = ''):
    if not algo:
        # not explicit algo, just use what's set by config
        algo = get_default_algo()

    if algo not in ALLOWED_ALGOS:
        ValueError(f'Bad encryption algorithm, should be {ALLOWED_ALGOS}, got: {algo}')

    enc_key = safe_bytes(enc_key)
    value = safe_bytes(value)

    if algo == 'aes':
        return encrypt_data(value, enc_key=enc_key)
    if algo == 'fernet':
        return Encryptor(enc_key).encrypt(value)

    return value


def decrypt_value(value: bytes, enc_key: bytes, algo: str = '', strict_mode: bool = False):

    if not algo:
        # not explicit algo, just use what's set by config
        algo = get_default_algo()
    if algo not in ALLOWED_ALGOS:
        ValueError(f'Bad encryption algorithm, should be {ALLOWED_ALGOS}, got: {algo}')

    enc_key = safe_bytes(enc_key)
    value = safe_bytes(value)
    safe = not strict_mode

    if algo == 'aes':
        return validate_and_decrypt_data(value, enc_key, safe=safe)
    if algo == 'fernet':
        return Encryptor(enc_key).decrypt(value, safe=safe)

    return value
