'''
This module defines two functions that demonstrate the use of the API key
authentication of the Cadenza Management API.

To use these, import the functions `build_mgmt_api_request_url` and
`sign_mgmt_api_request_url` from this file to generate a URL and signature
respectively.
'''
import hashlib
import hmac
import time
import base64
from urllib.parse import urlencode, urlparse, parse_qsl, urlunparse

def build_mgmt_api_request_url(original_url:str, update_args:dict=None) -> str:
    '''
    Build URL with timestamp query parameter for request to disy Cadenza using
    Management API with apikey-httpheader authentication.
    Prints the generated URL to stout.

    Args:
        original_url (str):   basic url of resource for request
        update_args (dict):   OPTIONAL dictionary of additional or updated query parameters
                              such as filter settings or requested datatype of response

    Returns:
        generated_url (str): URL with updated parameters and timestamp
    '''
    # update_args are optional
    update_args = update_args or {}
    # parse URL into components
    url_parts = urlparse(original_url)
    # update potentially exisiting query arguments and add timestamp (unix epoch time in ms)
    new_query = dict(parse_qsl(url_parts.query))
    new_query.update(update_args)
    new_query.update({'requestTimestamp' : int(time.time() * 1000)})
    new_query = urlencode(new_query)
    #re-encode updated url
    generated_url = urlunparse(url_parts._replace(query=new_query))
    print(f'Cadenza API URL:     {generated_url}')

    return generated_url


def sign_mgmt_api_request_url(original_url:str, api_secret:str) -> str:
    '''
    Generate signature for request to disy Cadenza using apikey-httpheader authentication.
    The signature will be generated by removing the resource locator (scheme, hostname, port)
    from the original URL, signing it with the secret key using the HMAC-SHA256 algorithm and
    Bas64 encoding the result.
    Prints the parts of the URL that are signed to stout.

    Args:
        original_url (str): Cadenza API request url that should be signed
        api_secret (str):   Cadenza secret that should be used to generate signature

    Returns:
        signature (str):    Base64 encoded signature string
    '''
    url_parts = urlparse(original_url)
    # only sign the resource locator part of the URL
    signature_url = urlunparse(url_parts._replace(scheme='', netloc=''))
    print(f'Signature URL:       {signature_url}')
    # secret is Base64 encoded hmac needs a byte array
    decoded_secret = base64.b64decode(api_secret)
    hmac_hash = hmac.new(decoded_secret, signature_url.encode(), hashlib.sha256).digest()
    # hash is a byte array, encode with Base64
    generated_signature = base64.b64encode(hmac_hash).decode()

    return generated_signature
