# Copyright (c) 2022 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

"""
Contains functions for creating CloudZero Resource Name (CZRN) identifiers for Azure resources.
CZRNs are used to unambiguously and uniquely identify any resource from any cloud provider, and even covers cases
where a resource might be observed from the Internet, and resources which may not have explicit existence
in a cloud environment.
"""

from typing import Mapping


def create_from_billing_lineitem(lineitem_fields: Mapping) -> str:
    azure_resource_id = lineitem_fields.get('lineitem_resourceid')
    product_region = lineitem_fields.get('product_region')

    if not azure_resource_id:
        raise ValueError('Cannot generate CZRN without resource ID.')

    if not product_region:
        raise ValueError('Cannot generate CZRN without region.')

    id_parts = [x.lower().replace(' ', '-') for x in azure_resource_id.split('/')]
    region = product_region.lower().replace(' ', '-')

    if len(id_parts) < 9 or \
       id_parts[1] != 'subscriptions' or \
       id_parts[3] != 'resourcegroups' or \
       id_parts[5] != 'providers':
        ###########################################
        # This resource ID is not in the expected format. We will attempt to generate a CZRN anyway.
        # We try and find the different parts and then convert all remaining parts into a single string.
        #
        # Often these may be specific services provided, not actual resources
        # Example: /subscriptions/12345678-aaaa-bbbb-cccc-defg12345678/providers/github/enterpriseaccount/business-12345
        #   /subscriptions/12345678-aaaa-bbbb-cccc-defg12345678/providers/microsoft.security/pricings/arm
        ###########################################
        subscription_idx = id_parts.index('subscriptions') + 1 if 'subscriptions' in id_parts else -1
        resourcegroup_idx = id_parts.index('resourcegroups') + 1 if 'resourcegroups' in id_parts else -1
        service_idx = id_parts.index('providers') + 1 if 'providers' in id_parts else -1
        resource_type_idx = id_parts.index('providers') + 2 if 'providers' in id_parts else -1

        if subscription_idx == -1 and resourcegroup_idx == -1 and service_idx == -1:
            ###########################################
            # We could not find any identifiable parts, so convert the resource ID into a single string.
            ###########################################
            return f'czrn:azure::{region}:::{"|".join(x for x in id_parts if x)}'

        def get_part(part_idx: int) -> str:
            return id_parts[part_idx] if part_idx >= 0 and len(id_parts) > part_idx else ''

        subscription_id = get_part(subscription_idx)
        resourcegroup_name = get_part(resourcegroup_idx)
        service = get_part(service_idx)
        resource_type = get_part(resource_type_idx)

        used_indexes = [x for x in [subscription_idx, resourcegroup_idx, service_idx, resource_type_idx] if x >= 0]
        unused_indexes = [x for x in range(len(id_parts)) if x not in used_indexes and x + 1 not in used_indexes]
        remaining_path = '|'.join([id_parts[x] for x in unused_indexes if id_parts[x]])

        return f'czrn:azure:{service}:{region}:{subscription_id}:{resource_type}:{resourcegroup_name}{"|" if remaining_path else ""}{remaining_path}' \
            if resourcegroup_name else f'czrn:azure:{service}:{region}:{subscription_id}:{resource_type}{":" if remaining_path else ""}{remaining_path}'
    if len(id_parts) == 9:
        ###########################################
        # This is the most typical resource ID format.
        #
        # Example: /subscriptions/12345678-aaaa-bbbb-cccc-defg12345678/resourceGroups/TestForBillingData_group/providers/Microsoft.Storage/storageAccounts/cloudzerobilling
        ###########################################
        return f'czrn:azure:{id_parts[6]}:{region}:{id_parts[2]}:{id_parts[7]}:{id_parts[4]}|{id_parts[8]}'
    if len(id_parts) == 13 and id_parts[9] == 'providers':
        ###########################################
        # This is a resource ID with a sub-provider.
        #
        # Example: /subscriptions/12345678-aaaa-bbbb-cccc-defg12345678/resourceGroups/TestForBillingData_group/providers/Microsoft.Storage/storageAccounts/cloudzerobilling/providers/Microsoft.EventGrid/extensionTopics/default
        ###########################################
        return f'czrn:azure:{id_parts[6]}:{region}:{id_parts[2]}:{id_parts[7]}:{id_parts[4]}|{id_parts[8]}|{id_parts[10]}|{id_parts[11]}|{id_parts[12]}'

    return f'czrn:azure:{id_parts[6]}:{region}:{id_parts[2]}:{id_parts[7]}:{id_parts[4]}|{id_parts[8]}|{"|".join(id_parts[9:])}'
