Private/Write-HydrationExecutionSummary.ps1

function Write-HydrationExecutionSummary {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [hashtable]$Settings,

        [Parameter(Mandatory)]
        [AllowEmptyCollection()]
        [array]$Results,

        [Parameter(Mandatory)]
        [datetime]$StartTime,

        [Parameter(Mandatory)]
        [bool]$WhatIfEnabled
    )

    $logParams = @{
        Message = 'Step 12: Generating Summary Report'
        Level   = 'Info'
    }
    Write-HydrationLog @logParams

    if ($Settings.reporting.outputPath) {
        $reportsPath = $Settings.reporting.outputPath
    } else {
        $tempBase = [System.IO.Path]::GetTempPath()
        $joinPathParams = @{
            Path      = $tempBase
            ChildPath = 'IntuneHydrationKit/Reports'
        }
        $reportsPath = Join-Path @joinPathParams
    }

    if (-not (Test-Path -Path $reportsPath)) {
        $newItemParams = @{
            Path     = $reportsPath
            ItemType = 'Directory'
            Force    = $true
            WhatIf   = $false
        }
        New-Item @newItemParams | Out-Null
    }

    $resultSummaryParams = @{
        Results = $Results
    }
    $summary = Get-ResultSummary @resultSummaryParams
    $joinPathParams = @{
        Path      = $reportsPath
        ChildPath = 'Hydration-Summary.md'
    }
    $reportPath = Join-Path @joinPathParams
    $jsonReportPath = $null
    $completionTime = Get-Date
    $timestamp = $completionTime.ToString('yyyy-MM-dd HH:mm:ss')
    $elapsedTime = $completionTime - $StartTime
    $elapsedTimeDisplay = '{0:00}:{1:00}:{2:00}' -f [Math]::Floor($elapsedTime.TotalHours), $elapsedTime.Minutes, $elapsedTime.Seconds
    $startedTimestamp = $StartTime.ToString('yyyy-MM-dd HH:mm:ss')

    $reportContent = @"
# Intune Hydration Summary
 
**Started:** $startedTimestamp
**Completed:** $timestamp
**Elapsed:** $elapsedTimeDisplay
**Tenant:** $($Settings.tenant.tenantId)
**Environment:** $($Settings.authentication.environment)
**Mode:** $(if ($WhatIfEnabled) { 'Dry-Run' } else { 'Live' })
 
## Summary
 
| Metric | Count |
|--------|-------|
| Total Operations | $($Results.Count) |
| Created | $($summary.Created) |
| Updated | $($summary.Updated) |
| Deleted | $($summary.Deleted) |
| Skipped | $($summary.Skipped) |
| Would Create | $($summary.WouldCreate) |
| Would Update | $($summary.WouldUpdate) |
| Would Delete | $($summary.WouldDelete) |
| Failed | $($summary.Failed) |
 
## Details by Type
 
"@


    $resultsByType = $Results | Group-Object -Property Type
    foreach ($typeGroup in $resultsByType) {
        $typeResults = $typeGroup.Group
        $created = ($typeResults | Where-Object { $_.Action -eq 'Created' }).Count
        $updated = ($typeResults | Where-Object { $_.Action -eq 'Updated' }).Count
        $deleted = ($typeResults | Where-Object { $_.Action -eq 'Deleted' }).Count
        $skipped = ($typeResults | Where-Object { $_.Action -eq 'Skipped' }).Count
        $wouldCreate = ($typeResults | Where-Object { $_.Action -eq 'WouldCreate' }).Count
        $wouldUpdate = ($typeResults | Where-Object { $_.Action -eq 'WouldUpdate' }).Count
        $wouldDelete = ($typeResults | Where-Object { $_.Action -eq 'WouldDelete' }).Count
        $failed = ($typeResults | Where-Object { $_.Action -eq 'Failed' }).Count

        $reportContent += @"
 
### $($typeGroup.Name)
- Created: $created
- Updated: $updated
- Deleted: $deleted
- Skipped: $skipped
- Would Create: $wouldCreate
- Would Update: $wouldUpdate
- Would Delete: $wouldDelete
- Failed: $failed
 
"@

    }

    if ($Results.Count -gt 0) {
        $reportContent += @"
 
## All Operations
 
| Timestamp | Type | Name | Action | ID | Details |
|-----------|------|------|--------|-----|---------|
"@


        $operationLines = foreach ($result in $Results) {
            if (-not $result.Name -and -not $result.Action) {
                continue
            }

            $timestampValue = if ($result.Timestamp) { $result.Timestamp } else { '' }
            $type = if ($result.PSObject.Properties['Type']) { $result.Type } else { '' }
            $name = if ($result.Name) { $result.Name } else { '' }
            $action = if ($result.Action) { $result.Action } else { '' }
            $id = if ($result.PSObject.Properties['Id']) { $result.Id } else { '' }
            $status = if ($result.Status) { $result.Status } else { '' }

            "| {0} | {1} | {2} | {3} | {4} | {5} |" -f $timestampValue, $type, $name, $action, $id, $status
        }

        $reportContent += "`n"
        $reportContent += ($operationLines -join "`n")
        $reportContent += "`n"
    }

    $reportContent += @"
 
## Important Notes
 
- **Conditional Access policies** were created in **DISABLED** state. Review and enable as needed.
- Review all configurations before enabling in production.
 
"@


    $outFileParams = @{
        FilePath = $reportPath
        Encoding = 'UTF8'
        WhatIf   = $false
    }
    $reportContent | Out-File @outFileParams
    $logParams = @{
        Message = "Summary report written to: $reportPath"
        Level   = 'Info'
    }
    Write-HydrationLog @logParams

    if ('json' -in $Settings.reporting.formats) {
        $joinPathParams = @{
            Path      = $reportsPath
            ChildPath = 'Hydration-Summary.json'
        }
        $jsonReportPath = Join-Path @joinPathParams
        @{
            Timestamp      = $timestamp
            Started        = $startedTimestamp
            Tenant         = $Settings.tenant.tenantId
            Environment    = $Settings.authentication.environment
            Mode           = if ($WhatIfEnabled) { 'DryRun' } else { 'Live' }
            ElapsedTime    = $elapsedTimeDisplay
            ElapsedSeconds = [Math]::Round($elapsedTime.TotalSeconds, 3)
            Summary        = $summary
            Results        = $Results
        } | ConvertTo-Json -Depth 10 | ForEach-Object {
            $jsonOutFileParams = @{
                FilePath = $jsonReportPath
                Encoding = 'UTF8'
                WhatIf   = $false
            }
            $_ | Out-File @jsonOutFileParams
        }
        $logParams = @{
            Message = "JSON report written to: $jsonReportPath"
            Level   = 'Info'
        }
        Write-HydrationLog @logParams
    }

    $logParams = @{
        Message = '=== Intune Hydration Kit Completed ==='
        Level   = 'Info'
    }
    Write-HydrationLog @logParams

    $summaryStatusLine = if ($WhatIfEnabled) {
        "Would Create: {0} | Would Update: {1} | Would Delete: {2} | Skipped: {3} | Failed: {4}" -f $summary.WouldCreate, $summary.WouldUpdate, $summary.WouldDelete, $summary.Skipped, $summary.Failed
    } else {
        "Created: {0} | Updated: {1} | Deleted: {2} | Skipped: {3} | Failed: {4}" -f $summary.Created, $summary.Updated, $summary.Deleted, $summary.Skipped, $summary.Failed
    }

    $summaryLines = @(
        ''
        (Format-HydrationDisplayMessage -Message 'Hydration Summary' -Style 'Section' -Emoji '📊')
        (Format-HydrationDisplayMessage -Message $summaryStatusLine -Style $(if ($WhatIfEnabled) { 'Info' } else { 'Success' }) -Emoji $(if ($WhatIfEnabled) { '🧪' } else { '✅' }))
        (Format-HydrationDisplayMessage -Message "Elapsed: $elapsedTimeDisplay" -Style 'Info' -Emoji '⏱️')
        (Format-HydrationDisplayMessage -Message "Reports: $reportPath" -Style 'Info' -Emoji '📝')
    )

    if ($jsonReportPath) {
        $summaryLines += Format-HydrationDisplayMessage -Message "JSON: $jsonReportPath" -Style 'Info' -Emoji '🧾'
    }

    foreach ($summaryLine in $summaryLines) {
        Write-Information $summaryLine -InformationAction Continue
    }

    if ($summary.Failed -gt 0) {
        $logParams = @{
            Message = "Completed with $($summary.Failed) failures"
            Level   = 'Warning'
        }
        Write-HydrationLog @logParams
    } elseif ($WhatIfEnabled) {
        $logParams = @{
            Message = 'Dry-run completed in {0}: {1} would create, {2} would update, {3} would delete, {4} skipped' -f $elapsedTimeDisplay, $summary.WouldCreate, $summary.WouldUpdate, $summary.WouldDelete, $summary.Skipped
            Level   = 'Info'
        }
        Write-HydrationLog @logParams
    } else {
        $logParams = @{
            Message = 'Completed successfully in {0}: {1} created, {2} updated, {3} deleted, {4} skipped' -f $elapsedTimeDisplay, $summary.Created, $summary.Updated, $summary.Deleted, $summary.Skipped
            Level   = 'Info'
        }
        Write-HydrationLog @logParams
    }

    return @{
        Summary            = $summary
        ReportPath         = $reportPath
        JsonReportPath     = $jsonReportPath
        ElapsedTime        = $elapsedTime
        ElapsedTimeDisplay = $elapsedTimeDisplay
    }
}