Private/Invoke-SPCVersionTrimmingInternal.ps1

function Invoke-SPCVersionTrimmingInternal {
    <#
    .SYNOPSIS
        Executes file version trimming across document libraries.
    .DESCRIPTION
        Trims historical versions exceeding KeepVersions limit and optionally adjusts library major version limit.
    .OUTPUTS
        [PSCustomObject] with LibrariesProcessed, FilesOptimizedCount, VersionsRemovedCount, StorageFreedMB
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)] [string]$SiteUrl,
        [Parameter()] [string[]]$LibraryTitle,
        [Parameter(Mandatory)] [int]$KeepVersions,
        [Parameter(Mandatory)] [int]$OlderThanDays,
        [Parameter(Mandatory)] [bool]$ApplyPolicy,
        [Parameter(Mandatory)] [bool]$DryRun,
        [Parameter(Mandatory)] [string]$AuditLogPath
    )

    begin {
        $siteConn = Connect-SPCSiteInternal -SiteUrl $SiteUrl -Context $script:SPCContext
        $librariesProcessed = 0
        $filesOptimized = 0
        $versionsRemoved = 0
        $freedBytes = [int64]0
        $now = (Get-Date).ToUniversalTime()

        $operatorUPN = if ($script:SPCContext -and -not [string]::IsNullOrWhiteSpace($script:SPCContext.OperatorUPN)) {
            $script:SPCContext.OperatorUPN
        } elseif ($script:SPCContext -and $script:SPCContext.TenantName) {
            "admin@$($script:SPCContext.TenantName).onmicrosoft.com"
        } else {
            'System'
        }
    }

    process {
        $lists = Get-PnPList -Connection $siteConn

        $docLibs = @()
        if ($null -ne $lists) {
            $docLibs = @($lists | Where-Object {
                $_.BaseTemplate -eq 101 -and -not $_.Hidden -and
                $_.Title -notin @('FormServerTemplates', 'Style Library', 'PreservationHoldLibrary', 'Preservation Hold Library', 'Site Assets', 'Site Pages')
            })
        }

        if ($LibraryTitle) {
            $docLibs = @($docLibs | Where-Object { $_.Title -in $LibraryTitle })
        }

        foreach ($lib in $docLibs) {
            $librariesProcessed++
            
            # Update Library MajorVersionLimit if requested and not simulation
            if ($ApplyPolicy -and -not $DryRun) {
                Set-PnPList -Identity $lib -MajorVersions $KeepVersions -Connection $siteConn -ErrorAction SilentlyContinue
            }

            Write-Verbose "Optimizing Library '$($lib.Title)' on $SiteUrl"
            $items = Get-PnPListItem -List $lib -Connection $siteConn -PageSize 500
            
            if ($null -ne $items) {
                foreach ($item in $items) {
                    if ($item.FileSystemObjectType -eq 'File') {
                        $file = Get-PnPProperty -ClientObject $item -Property File -Connection $siteConn
                        $versions = Get-PnPProperty -ClientObject $file -Property Versions -Connection $siteConn
                        
                        if ($null -ne $versions -and $versions.Count -gt $KeepVersions) {
                            $filesOptimized++
                            $toRemove = $versions | Select-Object -First ($versions.Count - $KeepVersions)
                            
                            foreach ($ver in $toRemove) {
                                $verSize = [int64]$ver.Length
                                $itemLeaf = if ($null -ne $item['FileLeafRef']) { $item['FileLeafRef'] } else { 'File' }
                                $itemRef = if ($null -ne $item['FileRef']) { $item['FileRef'] } else { '' }
                                $verCreatedBy = if ($ver.CreatedBy -and $ver.CreatedBy.Email) { $ver.CreatedBy.Email } else { 'Unknown' }

                                if ($DryRun) {
                                    Write-SPCAuditLogInternal `
                                        -LogPath $AuditLogPath `
                                        -SiteUrl $SiteUrl `
                                        -TargetType 'FileVersion' `
                                        -ItemId "$($item.Id)_$($ver.VersionLabel)" `
                                        -ItemTitle "$itemLeaf (v$($ver.VersionLabel))" `
                                        -FileRelativeUrl $itemRef `
                                        -SizeBytes $verSize `
                                        -DeletedDate $ver.Created `
                                        -DeletedByUPN $verCreatedBy `
                                        -OperatorUPN $operatorUPN `
                                        -ExecutionStatus 'SIMULATED' `
                                        -ErrorMessage ''

                                    $freedBytes += $verSize
                                    $versionsRemoved++
                                } else {
                                    try {
                                        # CSOM Delete version
                                        $ver.DeleteObject()
                                        if ($siteConn.Context) {
                                            $siteConn.Context.ExecuteQuery()
                                        }

                                        Write-SPCAuditLogInternal `
                                            -LogPath $AuditLogPath `
                                            -SiteUrl $SiteUrl `
                                            -TargetType 'FileVersion' `
                                            -ItemId "$($item.Id)_$($ver.VersionLabel)" `
                                            -ItemTitle "$itemLeaf (v$($ver.VersionLabel))" `
                                            -FileRelativeUrl $itemRef `
                                            -SizeBytes $verSize `
                                            -DeletedDate $ver.Created `
                                            -DeletedByUPN $verCreatedBy `
                                            -OperatorUPN $operatorUPN `
                                            -ExecutionStatus 'SUCCESS' `
                                            -ErrorMessage ''

                                        $freedBytes += $verSize
                                        $versionsRemoved++
                                    }
                                    catch {
                                        Write-SPCAuditLogInternal `
                                            -LogPath $AuditLogPath `
                                            -SiteUrl $SiteUrl `
                                            -TargetType 'FileVersion' `
                                            -ItemId "$($item.Id)_$($ver.VersionLabel)" `
                                            -ItemTitle "$itemLeaf (v$($ver.VersionLabel))" `
                                            -FileRelativeUrl $itemRef `
                                            -SizeBytes $verSize `
                                            -DeletedDate $ver.Created `
                                            -DeletedByUPN $verCreatedBy `
                                            -OperatorUPN $operatorUPN `
                                            -ExecutionStatus 'FAILED' `
                                            -ErrorMessage $_.Exception.Message
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    end {
        return [PSCustomObject]@{
            LibrariesProcessed   = $librariesProcessed
            FilesOptimizedCount  = $filesOptimized
            VersionsRemovedCount = $versionsRemoved
            StorageFreedMB       = [Math]::Round(($freedBytes / 1MB), 2)
        }
    }
}