Private/Read-NSPEntraAddressDomains.ps1

function Read-NSPEntraAddressDomains {
    [CmdletBinding()]
    param([Parameter(Mandatory)]$Queue, [Parameter(Mandatory)]$Inventory, [Parameter(Mandatory)]$Environment)
    if ($Queue.needsRevalidation) { throw 'Revalidate the queue before preparing addresses.' }
    if ([string]$Inventory.TenantId -ne [string]$Queue.tenantId -or [string]$Environment.TenantId -ne [string]$Queue.tenantId) {
        throw 'The environment, inventory and queue must belong to the same tenant.'
    }
    $selected = @($Queue.pairs | Where-Object decision -eq 'selected')
    if (-not $selected.Count) { Write-NSPConsoleLine -Message 'Select at least one pair before preparing addresses.' -Role Warning; return }
    $adSuffixes = @(); $cloudSuffixes = @()
    foreach ($pair in $selected) {
        $ad = @($Inventory.ADUsers | Where-Object { [string]$_.ObjectGUID -eq [string]$pair.adObjectGuid })
        $cloud = @($Inventory.CloudUsers | Where-Object { [string]$_.id -eq [string]$pair.cloudObjectId })
        if ($ad.Count -ne 1 -or $cloud.Count -ne 1) { throw 'Selected identities no longer resolve uniquely. Refresh and revalidate the inventory.' }
        if ([string]$ad[0].UserPrincipalName -match '@([^@]+)\z') { $adSuffixes += $Matches[1].ToLowerInvariant() }
        if ([string]$cloud[0].userPrincipalName -match '@([^@]+)\z') { $cloudSuffixes += $Matches[1].ToLowerInvariant() }
    }
    $adSuffixes = @($adSuffixes | Sort-Object -Unique)
    $cloudSuffixes = @($cloudSuffixes | Sort-Object -Unique)
    # Only verified names/default flags are used here. The planner owns actual forest suffix checks.
    $verified = @(Get-NSPEntraPairingUpnSuffixComparison -ExpectedTenantId $Queue.tenantId -Forest $Queue.forest -AvailableSuffix @())
    if (-not $verified.Count) { throw 'No verified cloud domains were returned. No target domain can be selected.' }
    $valid = { param($Name) $Name -and [uri]::CheckHostName($Name) -eq [UriHostNameType]::Dns -and $Name.Contains('.') }
    $old = $null
    if ($adSuffixes.Count -gt 1) {
        $old = Read-NSPMenu -Prompt 'Current AD UPN suffix: selected users have multiple suffixes' -Choices @($adSuffixes | ForEach-Object { [pscustomobject]@{Label=$_;Value=$_} }) -CancelLabel 'Back'
        if ($null -eq $old) { return }
        if ($old -notin $adSuffixes) { throw 'Choose a current suffix from the selected AD users.' }
    } else {
        $default = if ($adSuffixes.Count -eq 1) { $adSuffixes[0] } else { [string]$Environment.Domain }
        $options = @{Prompt='Current AD UPN suffix (DNS name only)';AllowBack=$true}
        if (& $valid $default) { $options.CurrentValue = $default.ToLowerInvariant() }
        $old = Read-NSPNonEmpty @options
        if (Test-NSPBackSignal $old) { return }
    }
    if (-not (& $valid ([string]$old))) { throw 'The current AD suffix must be a DNS name.' }
    $names = @($verified | ForEach-Object { $_.Suffix.ToLowerInvariant() } | Sort-Object -Unique)
    $custom = @($verified | Where-Object { -not $_.IsInitial -and $_.Suffix -notlike '*.onmicrosoft.com' } | ForEach-Object { $_.Suffix.ToLowerInvariant() } | Sort-Object -Unique)
    $default = $null
    if ($cloudSuffixes.Count -eq 1 -and $cloudSuffixes[0] -in $custom) { $default = $cloudSuffixes[0] }
    elseif ($custom.Count -eq 1) { $default = $custom[0] }
    if ($default) {
        $new = Read-NSPNonEmpty -Prompt 'Target verified cloud domain / AD UPN suffix (DNS name only)' -CurrentValue $default -AllowBack
        if (Test-NSPBackSignal $new) { return }
    } else {
        $choices = @($verified | Sort-Object Suffix | ForEach-Object {
            $flags = @(); if ($_.IsDefault) { $flags += 'tenant default' }; if ($_.IsInitial -or $_.Suffix -like '*.onmicrosoft.com') { $flags += 'initial/service domain' }
            [pscustomobject]@{Label=([string]$_.Suffix + $(if($flags.Count){' ('+($flags -join ', ')+')'}else{''}));Value=$_.Suffix}
        })
        $new = Read-NSPMenu -Prompt 'Target verified cloud domain: choose explicitly' -Choices $choices -CancelLabel 'Back'
        if ($null -eq $new) { return }
    }
    if (-not (& $valid ([string]$new)) -or $new -notin $names) { throw 'Choose a target from this tenant''s verified cloud domains.' }
    [pscustomobject]@{OldDomain=([string]$old).ToLowerInvariant();NewDomain=([string]$new).ToLowerInvariant()}
}