Private/Show-FSMResultSummary.ps1

function Show-FSMResultSummary {
    <#
    .SYNOPSIS
        Tallies a set of result objects by their Action and prints a clean summary.

    .DESCRIPTION
        Every action function in this module returns objects with an 'Action' property
        (Created, Skipped, Applied, Removed, Failed, WhatIf, ...). This helper counts
        them, prints a colour-coded one-line-per-outcome summary to the host, and
        returns the tally object so it can be captured or logged.

    .PARAMETER Result
        The collection of result objects to summarise.

    .PARAMETER Title
        A heading for the summary block.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [AllowNull()]
        [object[]]$Result,

        [Parameter(Mandatory)]
        [string]$Title
    )

    $items = @($Result | Where-Object { $_ -ne $null })

    Write-FSMStatus -Message "----- $Title -----" -Level Information

    if ($items.Count -eq 0) {
        Write-FSMStatus -Message 'No items processed.' -Level Warning
        return [pscustomobject]@{ Title = $Title; Total = 0 }
    }

    $byAction = $items | Group-Object -Property Action

    foreach ($group in ($byAction | Sort-Object Name)) {
        $level = switch ($group.Name) {
            'Created'  { 'Success' }
            'Applied'  { 'Success' }
            'Removed'  { 'Success' }
            'Skipped'  { 'Warning' }
            'WhatIf'   { 'Warning' }
            'Failed'   { 'Error' }
            default    { 'Information' }
        }
        Write-FSMStatus -Message ("{0,-9}: {1}" -f $group.Name, $group.Count) -Level $level
    }

    # Guard the lookup: under Set-StrictMode -Version Latest, calling .Count on the
    # $null returned when there is no 'Failed' group throws. @() makes it always safe.
    $failed = @($items | Where-Object { $_.Action -eq 'Failed' }).Count
    if ($failed) {
        Write-FSMStatus -Message "$failed item(s) FAILED - review the returned objects for details." -Level Error
    }

    $tally = [ordered]@{ Title = $Title; Total = $items.Count }
    foreach ($group in $byAction) { $tally[$group.Name] = $group.Count }
    return [pscustomobject]$tally
}