Public/New-LeanODBLogFile.ps1

function New-LeanODBLogFile {
    <#
    .SYNOPSIS
        Creates a lean OneDrive for Business ODL log archive from a diagnostic file.

    .DESCRIPTION
        Extracts a OneDrive for Business diagnostic file (.cab for Windows logs,
        .zip for Mac logs), separates relevant ODL log files from excluded categories
        (*.db, *.evtx, *.db-wal, *.log), compresses each excluded category into its
        own .zip side archive, removes ODL files not matching the specified date, and
        produces a final Parsed archive: {basename}-Parsed.cab for Windows logs
        (preserving folder structure via makecab), or {basename}-Parsed.zip for Mac logs.

    .PARAMETER Path
        Full path to the diagnostic file.
        Use a .cab file for Windows ODB logs; a .zip file for Mac ODB logs.
        Example: C:\Temp\OneDriveLogs_2023-11-16_16_26_27.cab

    .PARAMETER Date
        The date of the issue to filter ODL logs by, in yyyy-MM-dd format.
        Only ODL files whose name contains this date are kept in the final archive.
        Example: 2023-10-31

    .PARAMETER Platform
        Source platform of the diagnostic file.
        - Windows (default): expects a .cab file; includes *.odlsent in kept logs;
          suppresses non-critical deletion errors.
        - Mac: expects a .zip file; does not include *.odlsent.

    .PARAMETER NoSplit
        When specified, suppresses automatic splitting even if the output exceeds 15 MB.
        By default (omitted), the archive is automatically split into 14 MB parts when
        it exceeds 15 MB. Parts are written to a subfolder named {basename}-Parsed-Parts\
        following the naming convention: {basename}-Parsed.001.zip, .002.zip, ...

    .EXAMPLE
        New-LeanODBLogFile -Path "C:\Temp\OneDriveLogs_2023-11-16.cab" -Date "2023-10-31"

    .EXAMPLE
        New-LeanODBLogFile -Path "C:\Temp\OneDriveLogs_2023-11-16.zip" -Date "2023-10-31" -Platform Mac

    .EXAMPLE
        New-LeanODBLogFile -Path "C:\Temp\OneDriveLogs_2023-11-16.cab" -Date "2023-10-31" -NoSplit

    .OUTPUTS
        [string] Full path to the final archive when no split occurs.
        [string[]] Ordered paths of the part files when the archive is split.
    #>

    [CmdletBinding()]
    param(
        [Parameter()]
        [string] $Path = '',

        [Parameter()]
        [string] $Date = '',

        [Parameter()]
        [ValidateSet('Windows', 'Mac')]
        [string] $Platform = 'Windows',

        [Parameter()]
        [switch] $NoSplit
    )

    # Se Path ou Date não foram fornecidos, abre UI para coleta interativa.
    if (-not $PSBoundParameters.ContainsKey('Path') -or -not $PSBoundParameters.ContainsKey('Date')) {
        $ui = Show-LeanODBLogFileUI
        if ($null -eq $ui) { return }
        $Path     = $ui.Path
        $Date     = $ui.Date
        $Platform = $ui.Platform
        if ($ui.NoSplit) { $NoSplit = [switch]::Present }
    }

    # Validação manual (substitui Mandatory + ValidatePattern).
    if ([string]::IsNullOrWhiteSpace($Path))          { throw "Path is required." }
    if ([string]::IsNullOrWhiteSpace($Date))          { throw "Date is required." }
    if ($Date -notmatch '^\d{4}-\d{2}-\d{2}$')       { throw "Date must be in yyyy-MM-dd format." }
    if ($Platform -notin @('Windows', 'Mac'))         { throw "Platform must be 'Windows' or 'Mac'." }

    $ext         = [System.IO.Path]::GetExtension($Path).ToLower()
    $expectedExt = if ($Platform -eq 'Windows') { '.cab' } else { '.zip' }
    if ($ext -ne $expectedExt) {
        throw "Only log files generated with CollectSyncLogs.bat are supported. Therefore, a *.cab is expected for Windows and a *.zip for Mac."
    }

    # Instantiate processor — validates the source file path immediately.
    $processor = [ODBLogProcessor]::new($Path, $Date, $Platform)

    try {
        # Step 1: Extract
        Write-Host "Extracting '$($processor.SourceFile.Name)'..."
        $processor.ExtractSource()

        # Step 2: Collect files to keep
        Write-Host "Collecting ODL log files..."
        $odlFiles = $processor.CollectOdlFiles()

        # Step 3: Collect files to exclude
        Write-Host "Collecting excluded file categories..."
        $excludedGroups = $processor.CollectExcludedFiles()

        # Step 4: Rename excluded files (prefix with parent folder name)
        Write-Host "Renaming excluded files to prevent name collisions..."
        $renamedGroups = $processor.RenameExcludedFiles($excludedGroups)

        # Step 5: Compress each excluded category to a side zip
        Write-Host "`nCompressing excluded files into separate archives..."
        $processor.CompressExcluded($renamedGroups)

        # Step 6: Delete excluded and non-matching ODL files
        Write-Host "Removing excluded files..."
        $processor.DeleteExcluded($renamedGroups)

        Write-Host "Removing ODL files not matching date '$Date'..."
        $processor.DeleteNonMatchingOdl($odlFiles)

        # Step 7: Package remaining logs into the final archive (.cab for Windows, .zip for Mac)
        $outputFormat = if ($Platform -eq 'Windows') { 'cabinet (.cab)' } else { 'zip (.zip)' }
        Write-Host "`nPackaging lean ODL logs into $outputFormat archive..."
        $outputPath = $processor.CompressParsed()

        Write-Host "`nDone. Output: $outputPath" -ForegroundColor Green

        $fileSizeMB = (Get-Item -LiteralPath $outputPath).Length / 1MB

        if (-not $NoSplit.IsPresent -and $fileSizeMB -gt 15) {
            Write-Host "Splitting into 14 MB parts..."
            $parts = Split-ParsedFile -FilePath $outputPath
            $parts | ForEach-Object { Write-Host " $_" }
            Write-Host "Split complete: $($parts.Count) part(s)" -ForegroundColor Green
            return $parts
        }

        return $outputPath
    }
    finally {
        # Always clean up the extracted working directory, regardless of success or failure.
        Write-Host "Cleaning up working directory..."
        $processor.Cleanup()
    }
}