import time
import json
import base64


def parse_scitoken(token_string: str):
    """Parse a scitoken string and return the header, payload, and signature
    :param token_string: A scitoken as 3 '.'-separated base64 strings
    :return: header (dict), payload (dict), signature (str)
    :raises: ValueError if there is an error decoding the token
    """
    def prettytime(attr):
        return time.strftime("%F %T %z", time.localtime(int(payload[attr])))
    try:
        # b64decode errors if there's not enough padding; OTOH, no harm in too much padding
        header_b64, payload_b64, signature_b64 = [x + "==" for x in token_string.split(".")]
        header = json.loads(base64.urlsafe_b64decode(header_b64))
        payload = json.loads(base64.urlsafe_b64decode(payload_b64))
        signature = base64.urlsafe_b64decode(signature_b64)
        payload['exp'] = prettytime('exp')
        if 'nbf' in payload:
            payload['nbf'] = prettytime('nbf')
        if 'iat' in payload:
            payload['iat'] = prettytime('iat')

        return header, payload, signature
    except (AttributeError, TypeError, ValueError, json.JSONDecodeError) as err:
        raise ValueError(f"invalid token: {err}") from err