src/Public/Get-OpteraReclaimableLicense.ps1

function Get-OpteraReclaimableLicense {
    <#
    .SYNOPSIS
        Returns the reclaimable-license findings as objects for the pipeline (no file rendering).
    .DESCRIPTION
        Runs the same scan as Invoke-OpteraLicenseScan but emits objects instead of a report file.

        Gate behaviour mirrors the report so the named data cannot be obtained for free by switching
        cmdlets:
          - FULL (unlocked): emits one object per reclaimable account (the named remediation list).
          - FREE: emits the by-SKU rollup objects and warns how to unlock the named list.
    .EXAMPLE
        Get-OpteraReclaimableLicense | Where-Object MonthlyWasteUsd -gt 30 | Format-Table
    .EXAMPLE
        Get-OpteraReclaimableLicense -OfflineFixturePath .\tests\fixtures
    #>

    [CmdletBinding()]
    param(
        [string] $SearchBase,
        [string] $Server,

        # Scan every domain in the forest, not just the current one (multi-domain forests).
        [switch] $Forest,

        [ValidateRange(1, 3650)] [int] $StaleDays = 90,

        # OU(s) to suppress from the candidate list (full OU DN or a single component).
        [string[]] $ExcludeOu,

        [string] $PriceListPath,
        [string] $OfflineFixturePath,
        [string] $LicenseKey,
        [string] $TenantId,
        [string] $ClientId,
        [string] $CertificateThumbprint,
        [datetime] $ReferenceDate = (Get-Date)
    )

    $report = Invoke-LicenseReclaimScanCore -SearchBase $SearchBase -Server $Server -Forest:$Forest -StaleDays $StaleDays `
        -ExcludeOu $ExcludeOu -PriceListPath $PriceListPath -OfflineFixturePath $OfflineFixturePath -LicenseKey $LicenseKey `
        -TenantId $TenantId -ClientId $ClientId -CertificateThumbprint $CertificateThumbprint `
        -ReferenceDate $ReferenceDate

    if ($report.Mode -eq 'Full') {
        return $report.Reclaimable
    }

    Write-Warning ("Free mode: returning the aggregate per-SKU rollup only. {0} accounts (`${1:N0}/mo) are named in the full list - unlock with Unlock-OpteraLicenseReclaim." -f `
        $report.Summary.ReclaimableAccountCount, $report.Summary.TotalMonthlyUsd)

    # Prefer the richer owned-vs-reclaimable inventory (adds the tenant's prepaid/consumed seat counts per
    # SKU) when the tenant license inventory was available; fall back to the plain by-SKU rollup
    # otherwise. Both are aggregate - no per-account data - so either is safe to emit in Free mode.
    if ($report.Inventory -and @($report.Inventory).Count) {
        return $report.Inventory
    }
    return $report.Summary.BySku
}