#!/bin/bash
########################
# Azure Resource Counter
########################
# Version: 1.0.0
# Built: 2026-04-07 14:59:55
#
# Usage:
#   ./azure-assess.sh                    # Assess all accessible subscriptions
#   ./azure-assess.sh <sub-id-1> ...    # Assess specific subscriptions
#
################################################################################


set -e          # Exit on error
set -o pipefail # Catch errors in pipes


################################################################################
# SOURCE: config.sh
################################################################################

########################
# Configuration
########################

# Version
readonly VERSION="1.0.0"

# Output configuration
readonly OUTPUT_DIR="azure-assessment-$(date +%Y%m%d)"
readonly ACTIVITY_DAYS=30

# Timeouts (seconds)
readonly TIMEOUT_CLI=60
readonly TIMEOUT_QUERY=60

################################################################################
# SOURCE: outputs.sh
################################################################################

########################
# Output Definitions
########################

# Check if terminal supports colours
if [ -t 1 ]; then
    readonly GREEN='\033[0;32m'
    readonly RED='\033[0;31m'
    readonly YELLOW='\033[1;33m'
    readonly BLUE='\033[0;34m'
    readonly BOLD='\033[1m'
    readonly NC='\033[0m'
else
    # No colour support
    readonly GREEN=''
    readonly RED=''
    readonly YELLOW=''
    readonly BLUE=''
    readonly BOLD=''
    readonly NC=''
fi

################################################################################
# Output Functions
################################################################################

print_status() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

print_error() {
    echo -e "${RED}[ERROR]${NC} $1" >&2
}

print_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

print_header() {
    echo ""
    echo -e "${BLUE}$1${NC}"
    echo "========================================================================"
}

################################################################################
# SOURCE: checks.sh
################################################################################

########################
# Environment Checks
########################

 check_azure_cli() {
    echo "Checking Azure CLI"

    if ! command -v az &> /dev/null; then
        print_error "Azure CLI not found"
        return 1
    fi

    local version
    version=$(az version --query '"azure-cli"' -o tsv 2>/dev/null || echo "unknown")
    print_status "Azure CLI found (version: $version)"
    return 0
 }

 check_jq() {
     echo "Checking JQ"

     if ! command -v jq &> /dev/null; then
         print_warning "jq not found"
         return 1
     fi

     local version
     version=$(jq -V 2>/dev/null || echo "unknown")
     print_status "JQ found (version: $version)"
     return 0
 }


 check_authentication() {
     echo "Checking user Azure access"

     if ! az account show &> /dev/null; then
         print_error "Not logged in to Azure"
         return 1
     fi

     local user
     user=$(az account show --query user.name -o tsv 2>/dev/null)
     print_status "Authenticated as: $user"
     return 0
 }

 get_subscriptions() {
     echo "Checking accessible subscriptions"

     local sub_list
     sub_list=$(az account list -o json 2>/dev/null)

     if [ -z "$sub_list" ] || [ "$sub_list" = "[]" ]; then
         print_error "No accessible subscriptions found"
         return 1
     fi

     # Store subscriptions globally
     SUBSCRIPTIONS="$sub_list"

     local count
     count=$(echo "$SUBSCRIPTIONS" | jq 'length')

     print_status "Found $count accessible subscription(s)"
     return 0
 }

################################################################################
# SOURCE: queries.sh
################################################################################

########################
# Resource Graph Queries
########################
# Stateless Resources with Basic Count
query_stateless_resources() {
    local subscription_ids="$1"
    local resource_query='
    Resources
    | where type in~ (
        "microsoft.aad/domainservices",
        "microsoft.apimanagement/service",
        "microsoft.automation/automationaccounts",
        "microsoft.network/bastionhosts",
        "microsoft.batch/batchaccounts",
        "microsoft.cache/redis",
        "microsoft.ContainerRegistry/registries",
        "microsoft.documentdb/databaseaccounts",
        "microsoft.network/ddosprotectionplans",
        "microsoft.visualstudio/account",
        "microsoft.eventgrid/systemtopics",
        "microsoft.eventgrid/topics",
        "microsoft.eventhub/namespaces",
        "microsoft.network/azurefirewalls",
        "microsoft.keyvault/vaults",
        "microsoft.operationalinsights/workspaces",
        "microsoft.notificationhubs/namespaces/notificationhubs",
        "microsoft.search/searchservices",
        "microsoft.servicebus/namespaces",
        "microsoft.signalrservice/signalr",
        "microsoft.storage/storageaccounts",
        "microsoft.network/virtualnetworks",
        "microsoft.sql/managedinstances"
    )
    | extend DisplayType = case(
        type =~ "microsoft.aad/domainservices", "Entra Domain Services",
        type =~ "microsoft.apimanagement/service", "API Management Services",
        type =~ "microsoft.automation/automationaccounts", "Automation Accounts",
        type =~ "microsoft.network/bastionhosts", "Azure Bastions",
        type =~ "microsoft.batch/batchaccounts", "Batch Accounts",
        type =~ "microsoft.cache/redis", "Azure Cache for Redis",
        type =~ "microsoft.ContainerRegistry/registries", "Azure Container Registries",
        type =~ "microsoft.documentdb/databaseaccounts", "Cosmos DB Accounts",
        type =~ "microsoft.network/ddosprotectionplans", "DDoS Protection Plans",
        type =~ "microsoft.visualstudio/account", "Azure DevOps Organisations",
        type =~ "microsoft.eventgrid/systemtopics", "Event Grid Topics (system and custom)",
        type =~ "microsoft.eventgrid/topics", "Event Grid Topics (system and custom)",
        type =~ "microsoft.eventhub/namespaces", "Event Hubs Namespaces",
        type =~ "microsoft.network/azurefirewalls", "Azure Firewalls",
        type =~ "microsoft.keyvault/vaults", "Key Vaults",
        type =~ "microsoft.operationalinsights/workspaces", "Log Analytics Workspaces",
        type =~ "microsoft.notificationhubs/namespaces/notificationhubs", "Notification Hubs",
        type =~ "microsoft.search/searchservices", "AI Search",
        type =~ "microsoft.servicebus/namespaces", "Service Bus Namespaces",
        type =~ "microsoft.signalrservice/signalr", "SignalR Services",
        type =~ "microsoft.storage/storageaccounts", "Storage Accounts",
        type =~ "microsoft.network/virtualnetworks", "Virtual Networks",
        type =~ "microsoft.sql/managedinstances", "SQL Managed Instances",
        "Unknown"
    )
    | summarize count() by DisplayType
    | sort by DisplayType asc
    '
    local result
    result=$(az graph query -q "$resource_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq '.data' | jq -r '.[] | "\(.DisplayType),\(.count_)"')
    echo "$count"
}
# Populated App Gateways by WAF and non-WAF
query_app_gateways() {
    local subscription_ids="$1"
    local agw_query='
    Resources
    | where type =~ "microsoft.network/applicationgateways"
    | extend poolCount = array_length(properties.backendAddressPools)
    | where poolCount > 0
    | extend DisplayType = case(
        properties.sku.name contains "WAF", "Application Gateways (WAF)",
        "Application Gateways (non-WAF)"
    )
    | summarize count() by DisplayType
    '
    local result
    result=$(az graph query -q "$agw_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq '.data' | jq -r '.[] | "\(.DisplayType),\(.count_)"')
    echo "$count"
}

# Backup Vaults (RSVs with protected items)
query_backup_vaults() {
    local subscription_ids="$1"
    local rsv_query='
    Resources
    | where type == "microsoft.recoveryservices/vaults"
    | join kind=leftouter (
        RecoveryServicesResources
        | where type in~ (
            "microsoft.recoveryservices/vaults/backupfabrics/protectioncontainers/protecteditems",
            "microsoft.recoveryservices/vaults/replicationfabrics/replicationprotectioncontainers/replicationprotecteditems"
        )
        | extend vaultId = case(
            type contains "backupFabrics", tostring(split(id, "/backupFabrics/")[0]),
            type contains "replicationFabrics", tostring(split(id, "/replicationFabrics/")[0]),
            ""
        )
        | summarize count() by vaultId
    ) on $left.id == $right.vaultId
    | where isnotnull(count_) or count_ > 0
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$rsv_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}
# Azure CDN Classic
query_cdn_running() {
    local subscription_ids="$1"
    local cdn_query='
    resources
    | where type in~ ("microsoft.cdn/profiles", "microsoft.network/frontdoors")
    | where kind == "cdn"
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$cdn_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}
# Azure Container Instances Running
query_aci_running() {
    local subscription_ids="$1"
    local aci_query='
    Resources
    | where type == "microsoft.containerinstance/containergroups"
    | where properties.instanceView.state != "Stopped"
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$aci_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}

# MySQL Database Flexible Servers Running
query_mysql_running() {
    local subscription_ids="$1"
    local mysql_query='
    Resources
    | where type == "microsoft.dbformysql/flexibleservers"
    | where properties.state != "Disabled" and properties.state != "Stopped"
    | extend DisplayType = case(
        properties.replicationRole == "Replica", "DB For MySQL flexible server (replica)",
        "DB For MySQL Flexible Server (running)"
    )
    | summarize count() by DisplayType
    '
    local result
    result=$(az graph query -q "$mysql_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq '.data' | jq -r '.[] | "\(.DisplayType),\(.count_)"')
    echo "$count"
}
# PostgreSQL Database Flexible Servers Running
query_postgres_running() {
    local subscription_ids="$1"
    local postgres_query='
    Resources
    | where type == "microsoft.dbforpostgresql/flexibleservers"
    | where properties.state != "Disabled" and properties.state != "Stopped"
    | extend DisplayType = case(
        properties.replicationRole == "Replica", "DB For PostgreSQL flexible server (replica)",
        "DB For PostgreSQL Flexible Server (running)"
    )
    | summarize count() by DisplayType
    '
    local result
    result=$(az graph query -q "$postgres_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq '.data' | jq -r '.[] | "\(.DisplayType),\(.count_)"')
    echo "$count"
}
# Azure SQL PaaS Databases Running
query_sql_running() {
    local subscription_ids="$1"
    local sql_query='
    resources
    | where type == "microsoft.sql/servers/databases" and properties.status == "Online"
    | extend DisplayType = case(
        isnotnull(properties.secondaryType), "Azure SQL PaaS Database (replica)",
            "Azure SQL PaaS Database (running)"
        )
    | summarize count() by DisplayType
    '
    local result
    result=$(az graph query -q "$sql_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq '.data' | jq -r '.[] | "\(.DisplayType),\(.count_)"')
    echo "$count"
}
# Azure Public DNS Zones with additional record sets
query_dnsz_running() {
    local subscription_ids="$1"
    local dnsz_query='
    Resources
    | where type == "microsoft.network/dnszones"
    | where properties.numberOfRecordSets > 3
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$dnsz_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}
# Azure ExpressRoute Circuits Provisioned
query_expressroute_running() {
    local subscription_ids="$1"
    local expressroute_query='
    resources
    | where type == "microsoft.network/expressroutecircuits"
    | where  properties.circuitProvisioningState == "Enabled"
    | where properties.serviceProviderProvisioningState == "Provisioned"
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$expressroute_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}
# Azure FrontDoor Classic, Standard or Premium
query_frontdoor_running() {
    local subscription_ids="$1"
    local frontdoor_query='
    resources
    | where type in~ ("microsoft.cdn/profiles", "microsoft.network/frontdoors")
    | where kind != "cdn"
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$frontdoor_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}
# Web Apps and Function Apps running
query_web_function_apps() {
    local subscription_ids="$1"
    local app_query='
    Resources
    | where type == "microsoft.web/sites" or type == "microsoft.web/sites/slots"
    | where properties.state == "Running"
    | extend DisplayType = case(
        kind contains "functionapp", "Function Apps (running including slots)",
        "Web Apps (running including slots)"
    )
    | summarize count() by DisplayType
    '
    local result
    result=$(az graph query -q "$app_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq '.data' | jq -r '.[] | "\(.DisplayType),\(.count_)"')
    echo "$count"
}
# Load-balancers with backend pools
query_load_balancers() {
    local subscription_ids="$1"
    local lb_query='
    Resources
    | where type == "microsoft.network/loadbalancers"
    | extend poolCount = array_length(properties.backendAddressPools)
    | where poolCount > 0
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$lb_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}
# Logic Apps with triggers
query_logic_apps() {
    local subscription_ids="$1"
    local logic_query='
    Resources
    | where type == "microsoft.logic/workflows"
    | where properties.state == "Enabled"
    | where properties.definition.triggers != "{}"
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$logic_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}
# NAT Gateways with subnets
query_nat_gw() {
    local subscription_ids="$1"
    local natgw_query='
    Resources
    | where type == "microsoft.network/natgateways"
    | where isnotempty(properties.subnets)
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$natgw_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}
# P2S Gateways
query_p2s_gateways() {
    local subscription_ids="$1"
    local p2s_query='
    Resources
    | where type == "microsoft.network/virtualnetworkgateways"
    | where properties.gatewayType == "Vpn"
    | where isnotnull(properties.vpnClientConfiguration)
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$p2s_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}
query_vpn_gateways() {
    local subscription_ids="$1"
    local vpn_query='
    Resources
    | where type == "microsoft.network/virtualnetworkgateways"
    | where properties.gatewayType == "Vpn"
    | join kind=inner (
        Resources
        | where type == "microsoft.network/connections"
        | extend gatewayId = tostring(properties.virtualNetworkGateway1.id)
        | distinct gatewayId
    ) on $left.id == $right.gatewayId
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$vpn_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}
query_traffic_managers() {
    local subscription_ids="$1"
    local tm_query='
    resources
    | where type == "microsoft.network/trafficmanagerprofiles"
    | where properties.endpoints != '[]'
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$tm_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}
query_vwan_hubs() {
    local subscription_ids="$1"
    local vwan_query='
    resources
    | where type == "microsoft.network/virtualwans"
    | where isnotnull(properties.virtualHubs)
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$vwan_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}
query_vmss() {
    local subscription_ids="$1"
    local vmss_query='
    resources
    | where type == "microsoft.compute/virtualmachinescalesets"
    | where properties.virtualMachineProfile.extensionProfile.extensions !contains "AKS"
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$vmss_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}
# IaaS VMs Running or Stopped
query_running_vms() {

    local subscription_ids="$1"

    local vm_query='
    Resources
    | where type == "microsoft.compute/virtualmachines"
    | extend powerState = tostring(properties.extended.instanceView.powerState.code)
    | where powerState == "PowerState/running" or powerState == "PowerState/stopped"
    | summarize Count = count()
    '

    local result
    result=$(az graph query -q "$vm_query" -s $subscription_ids -o json 2>/dev/null)

    # Extract the count
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')

    echo "$count"
}
# AKS Clusters with Node Pools
query_aks_clusters() {
local subscription_ids="$1"
    local aks_query='
    Resources
    | where type == "microsoft.containerservice/managedclusters"
    | where properties.powerState.code =~ "Running"
    | where array_length(properties.agentPoolProfiles) > 0
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$aks_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}
# AKS Cluster Nodes
query_aks_cluster_nodes() {
    local subscription_ids="$1"
    local aks_nodes_query='
    Resources
    | where type =~ "microsoft.containerservice/managedclusters"
    | where properties.powerState.code =~ "Running"
    | mv-expand pool = properties.agentPoolProfiles
    | summarize Count = sum(toint(pool["count"]))
    '
    local result
    result=$(az graph query -q "$aks_nodes_query" -s $subscription_ids -o json 2>/dev/null)
    # Extract the total nodes count
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}
# Subscriptions with Defender for Cloud
query_sub_defender() {
local subscription_ids="$1"
    local defender_query='
    securityresources
    | where type == "microsoft.security/pricings"
    | where properties.pricingTier == "Standard"
    | distinct subscriptionId, name
    | summarize defenderPlans = make_list(name), planCount = count() by subscriptionId
    | summarize Count = count()
    '
    local result
    result=$(az graph query -q "$defender_query" -s $subscription_ids -o json 2>/dev/null)
    local count
    count=$(echo "$result" | jq -r '.data[0].Count // 0')
    echo "$count"
}

################################################################################
# SOURCE: export.sh
################################################################################

########################
# Export Function
########################
export_resource_counts() {

    local output_file="$1"
    local resource_type="$2"
    local count="$3"

    # Skip if count is empty or zero
    if [ -z "$count" ] || [ "$count" -eq 0 ] 2>/dev/null; then
        return 0
    fi

    # Append the count
    echo "$resource_type,$count" >> "$output_file"
}

################################################################################
# SOURCE: main.sh
################################################################################

########################
# Main Execution Script
########################
main() {
    # Parse command line arguments
    local specified_subs=""
    while [[ $# -gt 0 ]]; do
        specified_subs="$specified_subs $1"
        shift
    done

    # Banner
    echo "╔════════════════════════════════════════════════════════════════════╗"
    echo "║           Azure Resource Counter Tool                              ║"
    echo "╚════════════════════════════════════════════════════════════════════╝"
    echo ""

    # Pre-flight checks
    print_header "Environment Checks"
        check_azure_cli || exit 1
        check_jq || exit 1
        check_authentication || exit 1
        get_subscriptions || exit 1

    echo ""

    # Get subscriptions
    print_header "Subscription Discovery"

    local sub_ids
    if [ -n "$specified_subs" ]; then
        # Use specified subscriptions
        sub_ids=$(echo "$specified_subs" | xargs)
        print_status "Using specified subscription(s): $sub_ids"

        # Validate subscriptions exist and user has access
        for sub in $sub_ids; do
            if ! az account show --subscription "$sub" &>/dev/null; then
                print_error "Cannot access subscription: $sub"
                exit 1
            fi
        done
    else
        # Get all accessible subscriptions
        get_subscriptions || exit 1

        # List subscriptions
        echo "$SUBSCRIPTIONS" | jq -r '.[] | "  • \(.name) (\(.id))"'
        echo ""

        # Extract subscription IDs
        sub_ids=$(echo "$SUBSCRIPTIONS" | jq -r '.[].id' | xargs)
    fi

    local sub_count
    sub_count=$(echo "$sub_ids" | wc -w)
    print_status "Will scan $sub_count subscription(s)"

    # Create output directory
    mkdir -p "$OUTPUT_DIR"
    print_status "Output directory: $OUTPUT_DIR"
    echo ""
    local csv_file="$OUTPUT_DIR/resource-counts.csv"
    echo "ResourceType,Count" > "$csv_file"

    # Query resources
    print_header "Resource Discovery"
    # Multi result queries
    query_and_export_multi() {
        local query_func="$1"
        local sub_ids="$2"
        local csv_file="$3"

        local resource_count
        resource_count=$($query_func "$sub_ids")

        if [ -n "$resource_count" ]; then
            while IFS=',' read -r type count; do
                export_resource_counts "$csv_file" "$type" "$count"
            done <<< "$resource_count"
        fi
    }

    print_status "Counting Stateless Resources..."
    query_and_export_multi query_stateless_resources "$sub_ids" "$csv_file"
    print_status "Counting App Gateways..."
    query_and_export_multi query_app_gateways "$sub_ids" "$csv_file"
    print_status "Counting DB for MySQL flexible servers..."
    query_and_export_multi query_mysql_running "$sub_ids" "$csv_file"
    print_status "Counting DB for PostgreSQL flexible servers..."
    query_and_export_multi query_postgres_running "$sub_ids" "$csv_file"
    print_status "Counting Function and Web Apps..."
    query_and_export_multi query_web_function_apps "$sub_ids" "$csv_file"
    print_status "Counting SQL PaaS databases..."
    query_and_export_multi query_sql_running "$sub_ids" "$csv_file"

    # Single result queries
    query_and_export() {
        local query_func="$1"
        local display_name="$2"
        local sub_ids="$3"
        local csv_file="$4"

        print_status "Counting $display_name..."
        local count
        count=$($query_func "$sub_ids")
        export_resource_counts "$csv_file" "$display_name" "$count"
    }
    query_and_export query_aks_clusters "AKS Clusters (with node pools)" "$sub_ids" "$csv_file"
    query_and_export query_aks_cluster_nodes "AKS Cluster Nodes (running)" "$sub_ids" "$csv_file"
    query_and_export query_backup_vaults "Backup Vaults (RSVs with protected items)" "$sub_ids" "$csv_file"
    query_and_export query_cdn_running "CDN Classic profiles" "$sub_ids" "$csv_file"
    query_and_export query_sub_defender "Defender for Cloud" "$sub_ids" "$csv_file"
    query_and_export query_aci_running "Azure Container Instances (running)" "$sub_ids" "$csv_file"
    query_and_export query_dnsz_running "DNS Zones (public)" "$sub_ids" "$csv_file"
    query_and_export query_expressroute_running "Express Route Curcuits (provisioned)" "$sub_ids" "$csv_file"
    query_and_export query_frontdoor_running "FrontDoor Profiles (classic standard premium)" "$sub_ids" "$csv_file"
    query_and_export query_load_balancers "Load Balancers (with backend pools)" "$sub_ids" "$csv_file"
    query_and_export query_logic_apps "Logic Apps (enabled with triggers)" "$sub_ids" "$csv_file"
    query_and_export query_nat_gw "NAT Gateways (with subnets)" "$sub_ids" "$csv_file"
    query_and_export query_p2s_gateways "Point-to-Site VPN configurations" "$sub_ids" "$csv_file"
    query_and_export query_vpn_gateways "VPN Gateways (with connections)" "$sub_ids" "$csv_file"
    query_and_export query_running_vms "Virtual Machines (running or stopped)" "$sub_ids" "$csv_file"
    query_and_export query_traffic_managers "Traffic Manager Profiles (with endpoints)" "$sub_ids" "$csv_file"
    query_and_export query_vwan_hubs "Virtual WAN Hubs (with connections)" "$sub_ids" "$csv_file"
    query_and_export query_vmss "Virtual Machine Scale Sets (excluding AKS)" "$sub_ids" "$csv_file"
    # Completion
    print_header "Assessment Complete"
    print_status "Sorting results..."
    (head -n 1 "$csv_file" && tail -n +2 "$csv_file" | sort -t',' -k1) > "$csv_file.tmp"
    mv "$csv_file.tmp" "$csv_file"
    echo " "
    print_header "Print Results"
    cat "$csv_file"
    echo " "
    print_status "Output files:"
    ls -lh "$csv_file"
}

# Execute main
main "$@"
