import base64
from typing import Union, Optional

from Crypto import Random
from Crypto.Cipher import AES

from ..types import PDDVersion
from ...settings import config


def encrypt_registrar_password(pdd_version: PDDVersion, raw_password: str) -> (str, Optional[str], Optional[int]):
    if pdd_version == PDDVersion.old:
        return raw_password, None, None

    iv_init = Random.new().read(AES.block_size)
    iv_enc = base64.b32encode(iv_init)

    cipher = AES.new(config.registrar_store_password_secret, AES.MODE_CFB, iv_init)
    password_prepared = raw_password

    if len(raw_password) % 16:
        password_prepared = raw_password + '0' * (16 - len(raw_password) % 16)
    iv = iv_enc.decode('utf-8')
    password = base64.b32encode(
        cipher.encrypt(password_prepared)
    ).decode('utf-8')
    plength = len(raw_password)

    return password, iv, plength


def get_registrar_decrypted_password(password: str, pdd_version: PDDVersion, iv: str, plength: str) -> Union[str, bytes]:
    if pdd_version == PDDVersion.old:
        return password
    if not iv:
        return b''
    iv_dec = base64.b32decode(iv)
    cipher = AES.new(config.registrar_store_password_secret, AES.MODE_CFB, iv_dec)

    return cipher.decrypt(
        base64.b32decode(password)
    )[:plength]
