# global import, red is normal don't worry
import network_constants

import requests
import json
from typing import Dict

class TokenStash:
    '''
    used to keep track of already verified tokens in order to mitigate the traffic
    to the user-microservice
    '''
    trusted_tokens = {}
    roles = {}

    @staticmethod
    def add(token: str, username: str, role: str):
        '''
        adds a verified token to the stash
        '''
        TokenStash.trusted_tokens[token] = username
        TokenStash.roles[token] = role

    @staticmethod
    def is_token_cached(token: str) -> str:
        '''
        returns the associated username to a token, None otherwise
        '''

        if token in TokenStash.trusted_tokens and token in TokenStash.roles:
            return {"sub": TokenStash.trusted_tokens[token], "role": TokenStash.roles[token]}

        return None


def decodeToken(token: str) -> Dict:
    '''
    verifies the passed token on the user-microservice and returns a dictionary with the
    subject entry if the verification was successful, an error is raised otherwise

    @params:
            token - Required : JWT token from authorization header, must start with "Bearer "
    '''

    cached_username = TokenStash.is_token_cached(token)
    if cached_username != None:
        print("Re-using cached token!")
        return {"sub": cached_username}

    if not token.startswith("Bearer "):
        raise ValueError('Invalid JWT token (must be a Bearer string)')
    token = token[7:]

    response = requests.get(
        f'https://{REST_GATEWAY_HOSTNAME}/api/tokens/{token}')

    if response.status_code != 200:
        raise ValueError(
            f"Validation of token failed ({response.status_code})!")

    data = json.dumps(response.text)

    if not "username" in data:
        raise ValueError(
            f"Validation of token failed (missing field in verification response)!")

    TokenStash.add(token, data["username"], data["role"])
    return {"sub": data["username"], "role": data["role"]}
