import json
import boto3
import time

quicksight = boto3.client('quicksight')

# Function to check if a QuickSight Namespace exists for a company and creates one if it does not exist.
def check_namespace(aws_account_id, company):
    try:
        response = quicksight.describe_namespace(
            AwsAccountId=aws_account_id,
            Namespace=company
        )

        retries = 0
        
        while response['Namespace']['CreationStatus'] != "CREATED":
            response = quicksight.describe_namespace(
                AwsAccountId=aws_account_id,
                Namespace=company
            )
            retries += 1

            time.sleep(1.5 * retries)
            
    except Exception as e:
            raise Exception("Lambda GetQuickSightResponse.checkNameSpace function:" + str(e))

    return response

# Function to register the Cognito user in QuickSight in the specified namespace.
#TODO: Small wrapper over a try catch + API call, move out of a function.
def register_user(aws_account_id, email, company, quicksight_role):
    try:
        response = quicksight.register_user(
            AwsAccountId=aws_account_id,
            Namespace=company,
            IdentityType="IAM",
            IamArn=f"arn:aws:iam::{aws_account_id}:role/oktank-{company}",
            SessionName=email,
            Email=email,
            UserRole=quicksight_role,
            ExternalLoginFederationProviderType="COGNITO",
            ExternalLoginId=email,
            CustomPermissionsName='pbq-tenant'
        )

        response = quicksight.create_group_membership(
            MemberName=f"oktank-{company}/{email}",
            GroupName=company,
            AwsAccountId=aws_account_id,
            Namespace=company
        )
        
        return response
    except quicksight.exceptions.ResourceExistsException as e:
        return str(e)
    except Exception as e:
        raise Exception("Lambda GetQuickSightResponse.registerUser function:" + str(e))

# Call the generate_embed_url_for_registered_user API, depending on the embed type (Dashboard, Console)
def generate_console_embed_url(aws_account_id, get_user_arn_response):
    try:
        response = quicksight.generate_embed_url_for_registered_user(
            AwsAccountId=aws_account_id,
            SessionLifetimeInMinutes=30,
            UserArn=get_user_arn_response,
            ExperienceConfiguration={
                "QuickSightConsole": {"InitialPath": "/start"},
            },
        )
    except Exception as e:
        raise Exception("Lambda UserBasedURL.getEmbedUrl function: " + str(e))

    return response

def get_user_arn(aws_account_id, email, company):
    try:
        response = quicksight.describe_user(
            UserName=f"oktank-{company}/" + email,
            AwsAccountId=aws_account_id,
            Namespace=company,
        )
        return response["User"]["Arn"]
    except Exception as e:
        raise Exception(
            "Lambda GetQuickSightResponse.getUserArn function:" + str(e)
        )

def handler(event, context):
    print(event)

    aws_account_id = context.invoked_function_arn.split(":")[4]

    email = event["arguments"]["openIdToken"]["payload"]["email"]
    company_name = event["arguments"]["openIdToken"]["payload"]["custom:company"]
    
    # Determine what QuickSight Role newly created user will get.
    # "Admin" and "Author" are provisioned as QuickSight Authors. "Reader" is provisioned as QuickSight Reader.
    if event["arguments"]["openIdToken"]["payload"]["custom:role"].lower() == "author":
        quicksight_role = "AUTHOR"
    else:
        quicksight_role = "READER"

    # Main logic of handler
    try:
            check_namespace_response = check_namespace(aws_account_id, company_name)
            register_user_response = register_user(aws_account_id, email, company_name, quicksight_role)
            get_user_arn_response = get_user_arn(aws_account_id, email, company_name)
            get_embed_url_response = generate_console_embed_url(aws_account_id, get_user_arn_response)

            return json.dumps(
                {
                    "UserArn": get_user_arn_response,
                    "UserRegistration": register_user_response,
                    "EmbedUrl": get_embed_url_response,
                    "Namespace": check_namespace_response,
                }
            )
    except Exception as e:
        raise Exception("Lambda GetQuickSightResponse.handler function:" + str(e))