import json
from copy import deepcopy
from datetime import datetime
from base64 import b64encode, b64decode

from . import private_key, encoding


class Token:

    def __str__(self):
        return json.dumps(self.__dict__, indent=4)


class AuthToken(Token):

    def __init__(self, user_id="", login_id=""):
        self.user_id = user_id
        self.login_id = login_id
        self.date = datetime.utcnow().isoformat()


class AccessToken(AuthToken):

    def __init__(self, user_id, login_id):
        super().__init__(user_id=user_id, login_id=login_id)


class RenewToken(AuthToken):

    def __init__(self, user_id="", login_id="", server=""):
        super().__init__(user_id=user_id, login_id=login_id)
        self.server = server

    def get_access(self):
        return AccessToken(self.user_id, self.login_id)


def generate_access_token(renew_token: RenewToken):
    return renew_token.get_access()


def generate_tokens(user_id, login_id, server):
    renew_token = RenewToken(user_id=user_id, login_id=login_id, server=server)
    access_token = generate_access_token(renew_token)
    return renew_token, access_token


def sign_token(token: Token):
    signed_token = {"token": str(b64encode(str(token).encode(encoding)), encoding)}
    signed_token["signature"] = str(b64encode(private_key.sign(bytes(signed_token["token"], encoding))), encoding)
    return signed_token


def verify_token(token: str, signature: str):
    private_key.public_key().verify(b64decode(signature), bytes(token, encoding))
    token = str(b64decode(bytes(token, encoding)), encoding)
    return json.loads(token)


def verify_renew(token: str, signature: str):
    renew_token = RenewToken()
    renew_token.__dict__ = verify_token(token, signature)
    return renew_token


class WrongTokenError(Exception):
    pass


class TokenExpiredError(Exception):
    pass
