private/output/Invoke-OnCompleteHandler.ps1

function Invoke-OnCompleteHandler {
    <#
    .SYNOPSIS
        Finalizes async output - builds Results tab, updates console, hides loading spinner.
    #>

    # Does a lot. Wants breaking into smaller pieces.
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [hashtable]$Context
    )

    # Extract all context values for readability
    $Executor            = $Context.Executor
    $state               = $Context.State
    $outputData          = $Context.OutputData
    $outputDataByType    = $Context.OutputDataByType
    $consoleColorMap     = $Context.ConsoleColorMap
    $appendConsoleText   = $Context.AppendConsoleText
    $appendState         = $Context.AppendState
    $drainConsole        = $Context.DrainConsole
    $consoleParagraph    = $Context.ConsoleParagraph
    $consoleTextBox      = $Context.ConsoleTextBox
    $consoleTab          = $Context.ConsoleTab
    $autoScrollCheckbox  = $Context.AutoScrollCheckbox
    $errorsTabState      = $Context.ErrorsTabState
    $ensureErrorsTab     = $Context.EnsureErrorsTab
    $warningsTabState    = $Context.WarningsTabState
    $ensureWarningsTab   = $Context.EnsureWarningsTab
    $warningCount        = $Context.WarningCount
    $tabControl          = $Context.TabControl
    $tabNotifications    = $Context.TabNotifications
    $window              = $Context.Window
    $hideLoading         = $Context.HideLoading
    $loadingPanel        = $Context.LoadingPanel
    $loadingSpinner      = $Context.LoadingSpinner
    $loadingStack        = $Context.LoadingStack
    $loadingLabel        = $Context.LoadingLabel
    $progressBar         = $Context.ProgressBar
    $progressPanel       = $Context.ProgressPanel
    $headerTitle         = $Context.HeaderTitle
    $Title               = $Context.Title
    $HideUntilContent    = $Context.HideUntilContent
    $ParentWindow        = $Context.ParentWindow
    $statusSpinner       = $Context.StatusSpinner
    $statusSuccess       = $Context.StatusSuccess
    $statusWarning       = $Context.StatusWarning
    $statusIndicator     = $Context.StatusIndicator
    $colors              = $Context.Colors
    $ResultActions       = $Context.ResultActions
    $SingleSelect        = $Context.SingleSelect
    $varValues           = $Context.VarValues
    $funcDefs            = $Context.FuncDefs
    $capturedModules     = $Context.CapturedModules
    $defaultProgressUI   = $Context.DefaultProgressUI

    try {
        if ($state.DebugEnabled) {
            $eCount = [int]$errorsTabState.TotalErrors
            [Console]::WriteLine("[DEBUG] OnComplete fired - Results: $($outputData.Count), Types: $($outputDataByType.Count), Errors: $eCount")
        }

        if ($state.IsCancelled) {
            if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] OnComplete cancelled - window was closed") }
            return
        }

        # Stop queue polling timer and drain any remaining items
        if ($state.HostQueueTimer.IsEnabled) {
            $state.HostQueueTimer.Stop()
        }

        # Drain remaining pipeline queue items (critical for final batch)
        while ($Executor.PipelineQueueCount -gt 0) {
            $pipelineItems = $Executor.DrainPipelineQueue(500)
            if ($null -eq $pipelineItems -or $pipelineItems.Count -eq 0) { break }

            foreach ($item in $pipelineItems) {
                if ($null -eq $item) { continue }

                # Route ErrorRecords to Errors tab instead of Results
                if ($item -is [System.Management.Automation.ErrorRecord]) {
                    & $ensureErrorsTab
                    $displayRecord = New-ErrorDisplayRecord -ErrorRecord $item
                    [void]$errorsTabState.List.Add($displayRecord)
                    $errorsTabState.TotalErrors = [int]$errorsTabState.TotalErrors + 1

                    if ($errorsTabState.Tab.Visibility -eq 'Collapsed') {
                        $errorsTabState.Tab.Visibility = 'Visible'
                    }
                    continue
                }

                $displayName = Get-CleanTypeName -Item $item

                if (!$outputDataByType.Contains($displayName)) {
                    $outputDataByType[$displayName] = [System.Collections.Generic.List[object]]::new()
                }
                [void]$outputDataByType[$displayName].Add($item)
                [void]$outputData.Add([psobject]$item)
            }
        }

        # Errors picked up by this never went through the tick handler, so the header count has to refresh here too.
        if ($errorsTabState.Tab -and [int]$errorsTabState.TotalErrors -gt 0) {
            $errorsTabState.Tab.Header = "Errors ($([int]$errorsTabState.TotalErrors))"
        }

        if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Final drain - Results: $($outputData.Count), Types: $($outputDataByType.Count)") }
        if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Host queue remaining: $($Executor.HostQueueCount) items") }

        # Drain remaining host queue items
        $hostRecordsDrained = 0
        while ($Executor.HostQueueCount -gt 0) {
            $drained = & $drainConsole 500 -LeaveTabs
            if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Drained " + $drained + " host records") }
            $hostRecordsDrained += $drained
        }

        # Make Console tab visible if any host records drained
        if ($hostRecordsDrained -gt 0) {
            if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Making Console tab visible after draining " + $hostRecordsDrained + " records") }
            if ($consoleTab.Visibility -ne 'Visible') {
                $consoleTab.Visibility = 'Visible'
            }
            $tabNotifications.Console.UnreadCount += $hostRecordsDrained
            $consoleTab.Header = "Console (+$($tabNotifications.Console.UnreadCount))"
        }

        # Park the scroll where requested, top for ScrollToTop and bottom when autoscroll is on.
        if ($Context.ScrollToTop) {  $consoleTextBox.ScrollToHome() }
        elseif ($autoScrollCheckbox -and $autoScrollCheckbox.IsChecked) { $consoleTextBox.ScrollToEnd() }
        # Hide loading spinner on completion regardless
        & $hideLoading

        # If in HideUntilContent mode, check if there's any actual content
        if ($HideUntilContent) {
            # If window was already revealed by the final queue drain, don't close it
            if ($state.WindowRevealed) {
                if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] OnComplete: Window already revealed, skipping close check") }
            }
            else {
                $hasConsoleOutput = $consoleParagraph.Inlines.Count -gt 0
                $hasErrors = [int]$errorsTabState.TotalErrors -gt 0
                $hasWarnings = $warningCount.Value -gt 0
                $hasResults = $outputData.Count -gt 0

                if (!$hasConsoleOutput -and !$hasErrors -and !$hasWarnings -and !$hasResults) {
                    Write-Verbose "No content in any tab, closing silently"
                    # Activate parent window before closing to prevent console stealing focus
                    if ($ParentWindow) {
                        $ParentWindow.Activate()
                    }
                    $window.Close()
                    return
                }

                # Content exists but the window was never revealed, so reveal it now
                $state.WindowRevealed = $true
                $window.Visibility = 'Visible'
            }
        }

        $progressBar.IsIndeterminate = $false
        $progressBar.Value = 100
        $headerTitle.Text = "$Title - Complete"
        $progressPanel.Visibility = 'Collapsed'

        # Stop the spinner and show success or warning.
        $statusSpinner.Visibility = 'Collapsed'
        $hasErrors = [int]$errorsTabState.TotalErrors -gt 0
        $hasWarnings = $warningCount.Value -gt 0
        if ($hasErrors -or $hasWarnings) {
            $statusWarning.Visibility = 'Visible'
            $statusIndicator.ToolTip = "Complete with errors/warnings"

            # Update taskbar overlay to warning/error icon
            try {
                $errorOverlay = New-TaskbarOverlayIcon -GlyphChar ([PsUi.ModuleContext]::GetIcon('Alert')) -Color '#FFA500' -BackgroundColor '#FFFFFF'
                [PsUi.WindowManager]::SetTaskbarOverlay($window, $errorOverlay, 'Completed with warnings')
            }
            catch { Write-Debug "Suppressed taskbar warning overlay error: $_" }
        }
        else {
            $statusSuccess.Visibility = 'Visible'
            $statusIndicator.ToolTip = "Complete"

            # Update taskbar overlay to success checkmark
            try {
                $successOverlay = New-TaskbarOverlayIcon -GlyphChar ([PsUi.ModuleContext]::GetIcon('Accept')) -Color '#107C10' -BackgroundColor '#FFFFFF'
                [PsUi.WindowManager]::SetTaskbarOverlay($window, $successOverlay, 'Completed successfully')
            }
            catch { Write-Debug "Suppressed taskbar success overlay error: $_" }
        }

        if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] About to check outputData.Count = " + $outputData.Count) }

        if ($outputData.Count -gt 0) {
            if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Creating Results tab with " + $outputData.Count + " items") }

            # Convert to safe data array
            $dataArray = ConvertTo-SafeDataArray -DataArray @($outputData.ToArray())

            # A single hashtable is processed as a collection, otherwise it'd lack expandable values and the filter
            $presenter = Get-OutputPresenter -Data $dataArray

            # Create Results tab with toolbar using helper
            $toolbarResult = New-ResultsToolbar -Colors $colors -ResultActions $ResultActions
            $resultsTab       = $toolbarResult.Tab
            $resultsPanel     = $toolbarResult.Panel
            $toolbar          = $toolbarResult.Toolbar
            $toolbar2         = $toolbarResult.Toolbar2
            $rightToolbar     = $toolbarResult.RightToolbar
            $filterPanel      = $toolbarResult.FilterPanel
            $resultsBorder    = $toolbarResult.ResultsBorder
            $exportButton     = $toolbarResult.ExportButton
            $copyButton       = $toolbarResult.CopyButton
            $dropdownPopup    = $toolbarResult.DropdownPopup
            $actionDropdownMenuStack = $toolbarResult.ActionDropdownMenuStack

            $resultsTab.Header = "Results ($($outputData.Count))"

            # Display results
            if ($presenter -eq 'Collection') {
                $singleSelectParam = if ($SingleSelect) { @{ SingleSelect = $true } } else { @{} }
                $dataGrid = New-StyledDataGrid @singleSelectParam

                # Multi-type view with sub-TabControl
                if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Checking multi-type - outputDataByType.Count = " + $outputDataByType.Count) }
                foreach ($typeKey in $outputDataByType.Keys) {
                    if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Type key: " + $typeKey) }
                }

                # Limit to 10 tabs, with the overflow merged into an "Other" bucket
                $maxTypeTabs   = 10
                $sortedKeys    = $outputDataByType.Keys | Sort-Object { $outputDataByType[$_].Count } -Descending
                $typesToRender = @($sortedKeys | Select-Object -First $maxTypeTabs)
                $overflowTypes = @($sortedKeys | Select-Object -Skip $maxTypeTabs)

                if ($overflowTypes.Count -gt 0) {
                    $otherBucket = [System.Collections.Generic.List[object]]::new()
                    foreach ($overflowKey in $overflowTypes) {
                        foreach ($item in $outputDataByType[$overflowKey]) {
                            $otherBucket.Add($item)
                        }
                    }
                    $outputDataByType['Other'] = $otherBucket
                    $typesToRender += 'Other'
                    if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Merged " + $overflowTypes.Count + " overflow types into 'Other' bucket (" + $otherBucket.Count + " items)") }
                }

                if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Creating type-bucketed sub-TabControl with " + $typesToRender.Count + " tab(s)") }
                $subTabControl = [System.Windows.Controls.TabControl]::new()
                $subTabControl.Background = ConvertTo-UiBrush $colors.WindowBg
                $subTabControl.BorderThickness = [System.Windows.Thickness]::new(0)
                $subTabControl.Padding = [System.Windows.Thickness]::new(0)

                $firstDataGrid = $null
                foreach ($typeName in $typesToRender) {
                    $groupItems = $outputDataByType[$typeName]
                    if ($groupItems.Count -eq 0) { continue }

                    $subTab = [System.Windows.Controls.TabItem]::new()
                    $subTab.Header = "$typeName ($($groupItems.Count))"
                    Set-TabItemStyle -TabItem $subTab

                    $firstItem = $groupItems[0]
                    $isTextType = ($typeName -eq 'String') -or ($firstItem -is [string]) -or
                                  (($firstItem -is [ValueType]) -and !($firstItem -is [System.Collections.DictionaryEntry]))

                    if ($isTextType) {
                        $richTextBox = New-TextDisplayRichTextBox -Colors $colors -Lines $groupItems
                        $subTab.Content = $richTextBox
                        $subTab.Tag = 'TextType'
                        [void]$subTabControl.Items.Add($subTab)
                        if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Added TEXT sub-tab for type '" + $typeName + "' with " + $groupItems.Count + " lines") }
                        continue
                    }

                    if ($firstItem -is [System.Collections.DictionaryEntry]) {
                        $result = New-DictionarySubTab -GroupItems $groupItems -TypeName $typeName -IsDictionaryEntry -SingleSelect:$SingleSelect
                        [void]$subTabControl.Items.Add($result.Tab)
                        if ($null -eq $firstDataGrid) { $firstDataGrid = $result.DataGrid }
                        if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Added DICTIONARYENTRY sub-tab for type '" + $typeName + "'") }
                        continue
                    }

                    if ($firstItem -is [System.Collections.IDictionary]) {
                        $result = New-DictionarySubTab -GroupItems $groupItems -TypeName $typeName -SingleSelect:$SingleSelect
                        [void]$subTabControl.Items.Add($result.Tab)
                        if ($null -eq $firstDataGrid) { $firstDataGrid = $result.DataGrid }
                        if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Added DICTIONARY sub-tab for type '" + $typeName + "'") }
                        continue
                    }

                    # Create object DataGrid sub-tab using helper
                    $includeStatus = ($ResultActions -and $ResultActions.Count -gt 0)
                    $subTabParams = @{
                        GroupItems          = $groupItems
                        TypeName            = $typeName
                        SubTabControl       = $subTabControl
                        SingleSelect        = $SingleSelect
                        IncludeActionStatus = $includeStatus
                    }
                    $result = New-ObjectSubTab @subTabParams
                    [void]$subTabControl.Items.Add($result.Tab)
                    if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Added sub-tab for type '" + $typeName + "' with " + $groupItems.Count + " items") }

                    if ($null -eq $firstDataGrid) { $firstDataGrid = $result.DataGrid }
                }

                if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Multi-type complete - subTabControl has " + $subTabControl.Items.Count + " tabs") }
                $resultsBorder.Child = $subTabControl
                $dataGrid = $firstDataGrid

                # Add SelectionChanged handler to filter ResultAction buttons by ObjectType
                $capturedToolbar           = $toolbar
                $capturedDropdownMenuStack = $actionDropdownMenuStack
                $subTabControl.Add_SelectionChanged({
                    param($sender, $eventArgs)

                    # Ignore SelectionChanged events that walk up from child controls (e.g. DataGrid)
                    # Only process events that originated from the TabControl itself
                    if ($eventArgs.OriginalSource -ne $sender -and $eventArgs.OriginalSource -isnot [System.Windows.Controls.TabItem]) {
                        return
                    }

                    $selectedTab = $sender.SelectedItem
                    if (!$selectedTab) { return }

                    # Clear filter on the previously selected tab's DataGrid
                    if ($eventArgs.RemovedItems.Count -gt 0) {
                        $previousTab = $eventArgs.RemovedItems[0]
                        $prevGrid = Get-UiSubTabGrid -Tab $previousTab
                        if ($prevGrid) {
                            $view = [System.Windows.Data.CollectionViewSource]::GetDefaultView($prevGrid.ItemsSource)
                            if ($view -and $view.Filter) {
                                $view.Filter = $null
                                $view.Refresh()
                            }
                        }
                    }

                    # Update filter box enabled state based on tab's indexed status
                    $filterBox = $sender.Tag
                    if ($filterBox) {
                        if (![string]::IsNullOrEmpty($filterBox.Text)) {
                            $filterBox.Text = ''
                        }
                        elseif ($filterBox.Tag.RunFilter) {

                            if ($selectedTab.Tag -eq 'TextType') { & $filterBox.Tag.RunFilter $filterBox }
                            else {
                                $incomingGrid = Get-UiSubTabGrid -Tab $selectedTab
                                $incomingTag  = if ($incomingGrid) { $incomingGrid.Tag } else { $null }
                                if ($incomingTag -is [hashtable] -and $null -ne $incomingTag.Observable -and $null -ne $incomingTag.UnfilteredItems -and $incomingTag.Observable.Count -ne $incomingTag.UnfilteredItems.Count) {
                                    & $filterBox.Tag.RunFilter $filterBox
                                }
                            }
                        }

                        Set-UiSubTabToolbarState -Tab $selectedTab -FilterBox $filterBox
                    }

                    # Get the type name from the tab header
                    $selectedTypeName = $selectedTab.Header -replace '\s*\(\d+\)$', ''

                    $matchesObjectType = {
                        param($actionDef)
                        if (!$actionDef.ObjectType) { return $true }
                        $objectTypes = @($actionDef.ObjectType)
                        foreach ($ot in $objectTypes) {
                            if ($selectedTypeName -eq $ot -or $selectedTypeName -like "*.$ot" -or $selectedTypeName -match [regex]::Escape($ot)) {
                                return $true
                            }
                        }
                        return $false
                    }

                    # Filter individual buttons based on ObjectType
                    foreach ($child in $capturedToolbar.Children) {
                        if ($child -is [System.Windows.Controls.Button] -and $child.Tag -is [hashtable]) {
                            $actionDef = $child.Tag
                            $child.Visibility = if (& $matchesObjectType $actionDef) { 'Visible' } else { 'Collapsed' }
                        }
                    }

                    # Filter dropdown menu items based on ObjectType
                    if ($capturedDropdownMenuStack) {
                        $visibleCount = 0
                        foreach ($menuItem in $capturedDropdownMenuStack.Children) {
                            if ($menuItem -is [System.Windows.Controls.Button] -and $menuItem.Tag -is [hashtable]) {
                                $actionDef = $menuItem.Tag
                                $isVisible = & $matchesObjectType $actionDef
                                $menuItem.Visibility = if ($isVisible) { 'Visible' } else { 'Collapsed' }
                                if ($isVisible) { $visibleCount++ }
                            }
                        }

                        foreach ($child in $capturedToolbar.Children) {
                            if ($child -is [System.Windows.Controls.Button] -and $child.ToolTip -eq 'Available actions for selected items') {
                                $child.Visibility = if ($visibleCount -gt 0) { 'Visible' } else { 'Collapsed' }
                            }
                        }
                    }
                }.GetNewClosure())

                # Trigger initial filter on first tab
                if ($subTabControl.Items.Count -gt 0) {
                    $subTabControl.SelectedIndex = 0
                }

                # Add filter box and column visibility button
                $filterArgs = @{
                    SubTabControl = $subTabControl
                    RightToolbar  = $rightToolbar
                    FilterPanel   = $filterPanel
                    Toolbar2      = $toolbar2
                    SessionId     = $state.OwnerSessionId
                }
                [void](Add-MultiTypeFilterControls @filterArgs)

                # Attach action buttons using the helper
                if ($ResultActions -and $ResultActions.Count -gt 0) {
                    $allActionButtons = [System.Collections.Generic.List[object]]::new()
                    if ($actionDropdownMenuStack) {
                        foreach ($menuItem in $actionDropdownMenuStack.Children) {
                            if ($menuItem -is [System.Windows.Controls.Button] -and $menuItem.Tag -is [hashtable]) {
                                $allActionButtons.Add($menuItem)
                            }
                        }
                    }

                    # Tabs must exist before the result action handlers get them (result actions can produce their own errors/warnings)
                    & $ensureErrorsTab
                    & $ensureWarningsTab

                    $actionCaptures = @{
                        Window            = $window
                        State             = $state
                        DataGrid          = $dataGrid
                        ResultsBorder     = $resultsBorder
                        ConsoleTab        = $consoleTab
                        ConsoleParagraph  = $consoleParagraph
                        ConsoleColorMap   = $consoleColorMap
                        AppendConsoleText = $appendConsoleText
                        AppendState       = $appendState
                        ErrorsTab         = $errorsTabState.Tab
                        ErrorsList        = $errorsTabState.List
                        WarningsTab       = $warningsTabState.Tab
                        WarningsTextBox   = $warningsTabState.TextBox
                        WarningCount      = $warningCount
                        ProgressPanel     = $progressPanel
                        ProgressBar       = $progressBar
                        ProgressLabel     = $defaultProgressUI.Label
                        HeaderTitle       = $headerTitle
                        Title             = $Title
                        TabControl        = $tabControl
                        TabNotifications  = $tabNotifications
                        ErrorCount        = [int]$errorsTabState.TotalErrors
                        StatusSpinner     = $statusSpinner
                        StatusSuccess     = $statusSuccess
                        StatusWarning     = $statusWarning
                        StatusIndicator   = $statusIndicator
                        VarValues         = $varValues
                        FuncDefs          = $funcDefs
                        Modules           = $capturedModules
                    }

                    Add-ResultActionClickHandlers -Captures $actionCaptures -ActionButtons $allActionButtons -DropdownPopup $dropdownPopup
                }

                # Resolve the private helpers before the closures capture.
                $getVisiblePaths  = ${function:Get-UiDataGridVisibleColumnPaths}
                $formatExportRows = ${function:Format-UiDataGridExportRows}

                # $dataGrid is pinned to the FIRST subtab's grid. Copy and Export both need the grid the user is actually on, resolved when clicked
                $resolveActiveGrid = {
                    $activeGrid = $dataGrid
                    if ($resultsBorder.Child -is [System.Windows.Controls.TabControl]) {
                        $selectedTab = $resultsBorder.Child.SelectedItem
                        $activeGrid = Get-UiSubTabGrid -Tab $selectedTab
                    }
                    $activeGrid
                }.GetNewClosure()

                $copyButton.Add_Click({
                    $activeGrid = & $resolveActiveGrid
                    if (!$activeGrid) { return }

                    $props = @(& $getVisiblePaths -DataGrid $activeGrid)
                    $text  = & $formatExportRows -Items $activeGrid.ItemsSource -Properties $props | ConvertTo-Csv -NoTypeInformation | Out-String
                    if ([string]::IsNullOrEmpty($text)) { return }
                    [System.Windows.Clipboard]::SetText($text)
                    Start-UiButtonFeedback -Button $copyButton -OriginalIconChar ([PsUi.ModuleContext]::GetIcon('Copy'))
                }.GetNewClosure())

                # Show and hook the export button for datagrids
                $exportButton.Visibility = 'Visible'
                $exportButton.Add_Click({
                    $activeGrid = & $resolveActiveGrid
                    if (!$activeGrid) { return }

                    $saveDialog = [Microsoft.Win32.SaveFileDialog]::new()
                    $saveDialog.Filter = 'CSV files (*.csv)|*.csv|All files (*.*)|*.*'
                    $saveDialog.DefaultExt = '.csv'
                    $saveDialog.FileName = "export_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"

                    if ($saveDialog.ShowDialog()) {
                        $props = @(& $getVisiblePaths -DataGrid $activeGrid)
                        & $formatExportRows -Items $activeGrid.ItemsSource -Properties $props | Export-Csv -Path $saveDialog.FileName -NoTypeInformation
                        Start-UiButtonFeedback -Button $exportButton -OriginalIconChar ([PsUi.ModuleContext]::GetIcon('Export'))
                    }
                }.GetNewClosure())
            }
            else {
                # Text output with search capability
                $textLines = if ($dataArray.Count -gt 1) { $dataArray } else { @($dataArray[0].ToString()) }
                $richTextBox = New-TextDisplayRichTextBox -Colors $colors -Lines $textLines
                $resultsBorder.Child = $richTextBox

                Add-TextResultsFilter -RichTextBox $richTextBox -FilterPanel $filterPanel -Toolbar2 $toolbar2

                $copyButton.Add_Click({
                    $textRange = [System.Windows.Documents.TextRange]::new($richTextBox.Document.ContentStart, $richTextBox.Document.ContentEnd)
                    [System.Windows.Clipboard]::SetText($textRange.Text)
                    Start-UiButtonFeedback -Button $copyButton -OriginalIconChar ([PsUi.ModuleContext]::GetIcon('Copy'))
                }.GetNewClosure())
            }

            $resultsTab.Content = $resultsPanel
            if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Adding resultsTab to tabControl - resultsPanel has content: " + $resultsPanel.Children.Count) }
            $tabControl.Items.Insert(0, $resultsTab)
            $tabControl.SelectedIndex = 0
            if ($state.DebugEnabled) { [Console]::WriteLine("[DEBUG] Results tab inserted and selected") }
        }
        else {
            # No results, so check for console, error, or warning output.
            $hasConsoleOutput = $consoleParagraph.Inlines.Count -gt 0
            $hasErrors = [int]$errorsTabState.TotalErrors -gt 0
            $hasWarnings = $warningCount.Value -gt 0

            if ($hasConsoleOutput -or $hasErrors -or $hasWarnings) {
                if ($consoleTab.Visibility -eq 'Visible') {
                    $tabControl.SelectedItem = $consoleTab
                }
                elseif ($errorsTabState.Tab -and $errorsTabState.Tab.Visibility -eq 'Visible') {
                    $tabControl.SelectedItem = $errorsTabState.Tab
                }
                elseif ($warningsTabState.Tab -and $warningsTabState.Tab.Visibility -eq 'Visible') {
                    $tabControl.SelectedItem = $warningsTabState.Tab
                }
            }
            else {
                # No output at all, so show the success message.
                $loadingSpinner.Visibility = 'Collapsed'

                $successIcon = [System.Windows.Controls.TextBlock]@{
                    Text                = [PsUi.ModuleContext]::GetIcon('Accept')
                    FontFamily          = [PsUi.ModuleContext]::ActiveIconFontFamily
                    FontSize            = 48
                    Foreground          = ConvertTo-UiBrush '#107C10'
                    HorizontalAlignment = 'Center'
                    Margin              = [System.Windows.Thickness]::new(0, 0, 0, 12)
                }
                $loadingStack.Children.Insert(0, $successIcon)

                $loadingLabel.Text = 'Completed successfully. No output was returned.'
                $loadingLabel.FontSize = 13
                $loadingPanel.Visibility = 'Visible'
            }
        }
    }
    catch {
        [Console]::WriteLine("[PsUi] OnComplete error: " + $_.Exception.Message)
        if ($state.DebugEnabled) { [Console]::WriteLine("DEBUG ERROR StackTrace: " + $_.Exception.StackTrace) }

        # Insert the error in the console tab so the user isn't staring at a blank window
        try {
            if ($appendConsoleText -and $appendState) {
                & $appendConsoleText "Internal error rendering results: $($_.Exception.Message)" 'Red' $null -State $appendState
            }
        }
        catch { Write-Debug "Failed to surface OnComplete error to console" }
    }
}