Public/Helpers/Switch-Context.ps1

function Switch-Context {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
        [ArgumentCompleter({
                param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams)

                $contexts = Get-AzContext -ListAvailable
                $index = 1
                $contexts | ForEach-Object {
                    $friendlyName = "[$($_.Account.Id.Split('@')[0])] $(($_.Subscription.Name -replace '^\s+', ''))"
                    $indexedName = "$index - $friendlyName"

                    # Return matches for index, indexed name, or friendly name
                    if ($WordToComplete -eq '' -or
                        $index.ToString() -like "*$WordToComplete*") {
                        $index.ToString()
                        """$indexedName"""
                    }

                    $index++
                }
            })]
        [string]$SwitchTo
    )

    begin {
        Write-Verbose "Starting function $($MyInvocation.MyCommand.Name)"
        $MyInvocation.MyCommand.Name | Invoke-BlackCat
    }

    process {
        try {
            # Get all available contexts
            $contexts = Get-AzContext -ListAvailable

            if (!$SwitchTo) {
                # Display available contexts in a friendly format with added friendly names
                $index = 1
                $contexts | ForEach-Object {
                    # Create friendly name from subscription and account
                    $friendlyName = "[$($_.Account.Id.Split('@')[0])] $(($_.Subscription.Name -replace '^\s+', ''))"

                    [PSCustomObject]@{
                        Index        = $index++
                        FriendlyName = $friendlyName
                        Name         = $_.Name
                        Account      = $_.Account.Id
                        Subscription = $_.Subscription.Name
                        Tenant       = $_.Tenant.Id
                        Environment  = $_.Environment.Name
                        IsDefault    = $_.IsDefault
                    }
                } | Format-Table -AutoSize
                return
            } else {
                # Check if SwitchTo is an index number
                if ($SwitchTo -match '^\d+$') {
                    $indexNumber = [int]$SwitchTo
                    if ($indexNumber -gt 0 -and $indexNumber -le $contexts.Count) {
                        $targetContext = $contexts[$indexNumber - 1]
                    }
                    else {
                        Write-Message -FunctionName $($MyInvocation.MyCommand.Name) -Message "Index '$SwitchTo' is out of range (1-$($contexts.Count))" -Severity 'Error'
                        return
                    }
                }
                else {
                    # Enhance context search to include friendly name pattern
                    $targetContext = $contexts | Where-Object {
                        $friendlyName = "$($_.Subscription.Name) [$($_.Account.Id.Split('@')[0])]"
                        $_.Name -contains $SwitchTo -or
                        $_.Account.Id -contains $SwitchTo -or
                        $_.Subscription.Name -contains $SwitchTo -or
                        $friendlyName -eq $SwitchTo
                    }
                }

                if ($targetContext) {
                    Select-AzContext -InputObject $targetContext
                    $MyInvocation.MyCommand.Name | Invoke-BlackCat -ChangeProfile
                    Write-Message -FunctionName $($MyInvocation.MyCommand.Name) -Message "Switched to context: $SwitchTo" -Severity 'Information'

                    $currentContext = Get-AzContext
                    $userDetails = ConvertFrom-JWT -Base64JWT $script:authHeader.Values

                    [PSCustomObject]@{
                        Context      = "$($currentContext.Subscription.Name) [$($currentContext.Account.Id.Split('@')[0])]"
                        FirstName    = $userDetails.FirstName
                        LastName     = $userDetails.LastName
                        Account      = $currentContext.Account.Id
                        ObjectId     = $userDetails.ObjectId
                        Subscription = $currentContext.Subscription.Name
                        Tenant       = $currentContext.Tenant.Id
                        Environment  = $currentContext.Environment.Name
                        Roles        = $userDetails.Roles
                    }
                }
                else {
                    Write-Message -FunctionName $($MyInvocation.MyCommand.Name) -Message "Context '$SwitchTo' not found" -Severity 'Error'
                }
            }
        }
        catch {
            Write-Message -FunctionName $($MyInvocation.MyCommand.Name) -Message $($_.Exception.Message) -Severity 'Error'
        }
    }

    <#
    .SYNOPSIS
        Manages Azure PowerShell contexts.
 
    .DESCRIPTION
        Lists available Azure contexts and allows switching between them using friendly names or index numbers.
 
    .PARAMETER List
        Switch parameter to list all available contexts.
 
    .PARAMETER SwitchTo
        Specifies the context to switch to. Can be:
        - Index number (as displayed in the list)
        - Context name
        - Account ID
        - Subscription name
        - Friendly name
        Supports tab completion for friendly names.
 
    .EXAMPLE
        Get-AzureContext -List
        Lists all available Azure contexts.
 
    .EXAMPLE
        Get-AzureContext -SwitchTo "MySubscription"
        Switches to the context with the specified subscription name.
 
    .EXAMPLE
        Get-AzureContext -SwitchTo 2
        Switches to the context at index 2 in the list.
 
    .EXAMPLE
        Get-AzureContext
        Shows the current context information.
 
    .NOTES
        Author: Rogier Dijkman
    #>

}