function get_blob_file_path() {
    local blob_url=$1
    echo "$blob_url" | sed -E 's|https://[a-zA-Z0-9-]+\.blob\.core\.windows\.net/[a-zA-Z0-9-]+/?(.*)|\1|'
}

function get_blob_container() {
    local blob_url=$1
    echo "$blob_url" | sed -E 's|https://[a-zA-Z0-9-]+\.blob\.core\.windows\.net/([a-zA-Z0-9-]+)/?.*|\1|'
}

function get_blob_storage_account() {
    local blob_url=$1
    echo "$blob_url" | sed -E 's|https://([a-zA-Z0-9-]+)\.blob\.core\.windows\.net.*|\1|'
}

function download_blob() {
    local blob_url=$1
    local local_file=$2
    local storage_account=$(get_blob_storage_account "$blob_url")
    local container=$(get_blob_container "$blob_url")
    local file_path=$(get_blob_file_path "$blob_url")
    az storage blob download \
        --only-show-errors --output none --no-progress \
        --account-name "${storage_account}" --container-name "$container" \
        --name "$file_path" --file "${local_file}"
}

function upload_blob() {
    local local_file=$1
    local blob_url=$2
    shift 2

    local storage_account=$(get_blob_storage_account "$blob_url")
    local container=$(get_blob_container "$blob_url")
    local file_path=$(get_blob_file_path "$blob_url")
    az storage blob upload \
        --only-show-errors --output none --no-progress \
        --account-name "${storage_account}" --container-name "$container" \
        --name "$file_path" --file "${local_file}" "$@"
}

function wait_for_services_ready() {
    set +e # Ignore error when kubectl command fails

    local -n services_ref="$1"
    local -n ns_ref="$2"
    local timeout="${JOB_TIMEOUT:-600}" # 10 mins
    local interval="${JOB_CHECK_INTERVAL:-10}"

    echo "waiting for services ready"
    local start_time=$(date +%s)
    local svc=""
    while [[ $(($(date +%s) - $start_time)) -lt $timeout ]]; do
        local all_ready="true"
        for svc in "${!services_ref[@]}"; do
            if [[ ${services_ref[$svc]} == "true" ]]; then
                continue
            else
                all_ready="false"
            fi

            if [[ "${svc}" == "provider.pkg.crossplane.io/"* ]]; then
                local ready=$(kubectl get ${svc} -n $ns_ref -ojsonpath='{.status.conditions[?(@.type=="Healthy")].status}' 2>/dev/null)
                if [[ $? -eq 0 ]]; then
                    if [[ "$ready" == "True" ]]; then
                        services_ref[$svc]="true"
                        echo "Service $svc in $ns_ref is ready"
                    fi
                fi
            else
                local ready=$(kubectl get ${svc} -n $ns_ref -ojsonpath='{.status.readyReplicas}' 2>/dev/null)
                if [[ $? -eq 0 ]]; then
                    if [[ $ready -ge 1 ]]; then
                        services_ref[$svc]="true"
                        echo "Service $svc in $ns_ref is ready"
                    fi
                fi
            fi
        done

        if $all_ready; then
            echo "All services ready!"
            return 0
        else
            sleep "$interval"
        fi
    done

    # Report unready services
    echo "Following services in $ns_ref are unready:"
    for svc in "${!services_ref[@]}"; do
        if [[ ${services_ref[$svc]} == "false" ]]; then
            echo $svc
        fi
    done
    return 1
}

function azureLogin() {
    local tenant_id=$1
    local client_id=$2
    local id_token=$(curl -H "Authorization: Bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" "${ACTIONS_ID_TOKEN_REQUEST_URL}" | yq -r '.value')
    az login --federated-token $id_token --service-principal -u $client_id -t $tenant_id
}

function wait_for_services_removed() {
    set +e # Ignore error when kubectl command fails

    local -n services_ref="$1"
    local -n ns_ref="$2"
    local timeout="${JOB_TIMEOUT:-600}"  # 10 mins
    local interval="${JOB_CHECK_INTERVAL:-10}"

    echo "waiting for services removed"
    local start_time=$(date +%s)
    local svc=""
    while [[ $(($(date +%s) - $start_time)) -lt $timeout ]]; do
        local all_removed=true
        for svc in "${!services_ref[@]}"; do
            if [[ ${services_ref[$svc]} == "true" ]]; then
                continue
            else
                all_removed=false
            fi

            result=$(kubectl get ${svc} -n ${ns_ref} --ignore-not-found 2>/dev/null)
            if [[ $? -eq 0 ]]; then
              if [ -z "$result" ]; then
                services_ref[$svc]="true"
                echo "service ${svc} was removed"
              fi
            elif [[ $result == *"the server doesn't have a resource type"* ]]; then
              services_ref[$svc]="true"
              echo "service type of ${svc} was not found"
            else
              echo "failed to get service ${svc} status"
              return 1
            fi
        done

        if $all_removed; then
            echo "All services removed!"
            return 0
        else
            sleep "$interval"
        fi
    done

    # Report unready services
    echo "Following services_ref are still not removed:"
    for svc in "${!services_ref[@]}"; do
        if [[ ${services_ref[$svc]} == "false" ]]; then
            echo $svc
        fi
    done
    return 1
}
