# Copyright (c) 2021 CloudZero - ALL RIGHTS RESERVED - PROPRIETARY AND CONFIDENTIAL
# Unauthorized copying of this file and/or project, via any medium is strictly prohibited.
# Direct all questions to legal@cloudzero.com

from pprint import pformat

import cachetools.func
import pyfaaster.aws.tools as faaster_aws_tools
import requests
from czc.constants import FEATURE_NAME
from jose import jwt
from czc.smoke.helpers import ok

logger = faaster_aws_tools.setup_logging(FEATURE_NAME)


@cachetools.func.lru_cache(maxsize=16)
def token_to_ids(tenant, token):
    keyset = _get_keyset_cached(tenant)
    decoded_token = _decode_token(token, keyset)
    return decoded_token['https://cloudzero.com/organization_id'], decoded_token['https://cloudzero.com/user_id']


def _decode_token(token, keyset_dict):
    logger.debug(f'Decoding [{token}]')
    logger.debug(f'Using keyset_dict: [{keyset_dict}]')
    options = {
        'verify_signature': True,
        'verify_iat': False,
        'verify_exp': False,
        'verify_nbf': False,
        'verify_aud': False,
        'verify_iss': False,
        'verify_sub': False,
        'verify_jti': False,
        'verify_at_hash': False,
        'leeway': 0,
    }
    return jwt.decode(token, keyset_dict, options=options)


@cachetools.func.lru_cache(maxsize=1)
def _get_keyset_cached(tenant):
    openid_config = _get_openid_config_cached(tenant)
    url = openid_config['jwks_uri']
    response = requests.get(url)
    assert response.status_code == 200
    return response.json()


@cachetools.func.lru_cache(maxsize=1)
def _get_openid_config_cached(tenant):
    url = f'https://{tenant}/.well-known/openid-configuration'
    response = requests.get(url)
    assert response.status_code == 200
    return response.json()


@cachetools.func.lru_cache(maxsize=16)
@ok('Fetching Token')
def fetch(namespace, tenant, user, scopes='openid profile email'):
    tenant, client_id, client_secret = tenant
    username, password = user
    url = f'https://{tenant}/oauth/token'

    params = {
        'grant_type': 'password',
        'client_id': client_id,
        'client_secret': client_secret,
        'audience': f'cz-{namespace}-feature-api',
        'username': username,
        'password': password,
        'scope': scopes,
    }
    logger.debug(f'Sending request to {url}: {pformat(params)}')
    response = requests.post(url, data=params).json()
    logger.debug(f'response: {response}')
    return response['access_token']
