Public/New-CwReport.ps1

function New-CwReport {
    <#
    .SYNOPSIS
        Renders the self-contained HTML report from one or many snapshots.
    .DESCRIPTION
        Inline CSS/JS, vanilla SVG charts, no CDN dependency - the resulting
        file opens offline and can be mailed to ops or the customer. With
        -Baseline a trend section (new / removed / approaching expiries vs. the
        baseline snapshot) is added via Compare-CwSnapshot. Snapshots from
        multiple tenants are grouped per tenant, customer data is never mixed
        within a table.
    .EXAMPLE
        Invoke-CertWatchtowerScan -TenantConfig .\tenants\*.json -SnapshotPath .\snapshots |
            New-CwReport -Baseline (Get-CwSnapshot -Latest -Path .\snapshots -Skip 1) `
                         -OutFile ".\out\cert-watchtower_$(Get-Date -Format yyyyMMdd).html"
    #>

    [CmdletBinding(SupportsShouldProcess)]
    [OutputType([System.IO.FileInfo], [string])]
    param(
        [Parameter(Mandatory, ValueFromPipeline, Position = 0)]
        [object[]]$Snapshot,

        [object[]]$Baseline,

        [string]$OutFile,

        [string]$Title = 'cert-watchtower fleet report',

        [switch]$PassThru
    )

    begin {
        $snapshots = [System.Collections.Generic.List[object]]::new()
    }

    process {
        foreach ($snap in $Snapshot) { $snapshots.Add($snap) }
    }

    end {
        if ($snapshots.Count -eq 0) {
            throw 'No snapshots supplied.'
        }

        $trend = $null
        if ($Baseline) {
            $trend = Compare-CwSnapshot -ReferenceSnapshot $Baseline -DifferenceSnapshot $snapshots.ToArray()
        }

        $html = Write-CwHtmlReport -Snapshot $snapshots.ToArray() -Trend $trend -Title $Title

        if ($OutFile) {
            $dir = Split-Path -Path $OutFile -Parent
            if ($dir -and -not (Test-Path -Path $dir)) {
                $null = New-Item -Path $dir -ItemType Directory -Force
            }
            if ($PSCmdlet.ShouldProcess($OutFile, 'Write HTML report')) {
                Set-Content -Path $OutFile -Value $html -Encoding utf8
                Get-Item -Path $OutFile
            }
            if ($PassThru) { $html }
        }
        else {
            $html
        }
    }
}