Private/Utility/Get-SmartDefaultRegions.ps1

function Get-SmartDefaultRegions {
    <#
    .SYNOPSIS
        Returns context-aware default regions based on cloud environment and user timezone.
    .DESCRIPTION
        Cloud environment takes priority: Gov/China tenants get their sovereign regions.
        For commercial cloud, the local timezone is used to pick the nearest geo.
    .OUTPUTS
        Hashtable with keys: Regions (string[]), Source (string)
    #>

    [CmdletBinding()]
    [OutputType([hashtable])]
    param(
        [Parameter(Mandatory = $false)]
        [string]$CloudEnvironment
    )

    # Signal 1: Cloud environment (sovereign clouds always override timezone)
    if (-not $CloudEnvironment) {
        try {
            $CloudEnvironment = (Get-AzContext).Environment.Name
        }
        catch {
            Write-Verbose "Get-SmartDefaultRegions: Get-AzContext failed, falling back to AzureCloud. Error: $($_.Exception.Message)"
            $CloudEnvironment = 'AzureCloud'
        }
    }

    switch ($CloudEnvironment) {
        'AzureUSGovernment' {
            return @{
                Regions = @('usgovvirginia', 'usgovtexas', 'usgovarizona')
                Source  = 'Cloud: AzureUSGovernment'
            }
        }
        'AzureChinaCloud' {
            return @{
                Regions = @('chinaeast', 'chinaeast2', 'chinanorth')
                Source  = 'Cloud: AzureChinaCloud'
            }
        }
    }

    # Signal 2: Local timezone -> geo hint (commercial cloud only)
    # BaseUtcOffset is intentional — it excludes DST so region selection stays stable year-round
    $utcOffset = [System.TimeZoneInfo]::Local.BaseUtcOffset.TotalHours

    if ($utcOffset -ge -10 -and $utcOffset -lt -2) {
        $regions = @('eastus', 'eastus2', 'centralus')
        $geo = 'Americas'
    }
    elseif ($utcOffset -ge -2 -and $utcOffset -lt 3.5) {
        $regions = @('westeurope', 'northeurope', 'uksouth')
        $geo = 'Europe'
    }
    elseif ($utcOffset -ge 3.5 -and $utcOffset -lt 7) {
        $regions = @('centralindia', 'uaenorth', 'westindia')
        $geo = 'India/MiddleEast'
    }
    elseif ($utcOffset -ge 7 -and $utcOffset -lt 10) {
        $regions = @('eastasia', 'southeastasia', 'japaneast')
        $geo = 'AsiaPacific'
    }
    elseif ($utcOffset -ge 10 -and $utcOffset -le 13) {
        $regions = @('australiaeast', 'australiasoutheast', 'eastasia')
        $geo = 'Australia'
    }
    else {
        $regions = @('eastus', 'eastus2', 'centralus')
        $geo = 'Fallback'
    }

    # Format offset as UTC+05:30 / UTC-04:00
    $offsetSign = if ($utcOffset -ge 0) { '+' } else { '-' }
    $absOffset = [Math]::Abs($utcOffset)
    $offsetHours = [Math]::Floor($absOffset)
    $offsetMinutes = [Math]::Round(($absOffset - $offsetHours) * 60)
    $formattedOffset = '{0}{1:D2}:{2:D2}' -f $offsetSign, [int]$offsetHours, [int]$offsetMinutes

    return @{
        Regions = $regions
        Source  = "Timezone: $([System.TimeZoneInfo]::Local.Id) (UTC$formattedOffset) -> $geo"
    }
}