EnhancedFileManagerAO.psm1

#Region '.\Private\Check-DiskSpace.ps1' -1

function Check-DiskSpace {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]$Path,
        [Parameter(Mandatory = $true)]
        [int]$RequiredSpaceGB
    )

    begin {
        Write-EnhancedLog -Message "Starting Check-DiskSpace function" -Level "INFO"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    process {
        try {
            $drive = Get-PSDrive -PSProvider FileSystem | Where-Object { $_.Root -eq ([System.IO.Path]::GetPathRoot($Path)) }
            if ($drive -and ($drive.Free -lt ($RequiredSpaceGB * 1GB))) {
                Write-EnhancedLog -Message "Not enough disk space on drive $($drive.Root). Required: $RequiredSpaceGB GB, Available: $([math]::round($drive.Free / 1GB, 2)) GB." -Level "ERROR"
                throw "Not enough disk space on drive $($drive.Root)."
            } else {
                Write-EnhancedLog -Message "Sufficient disk space available on drive $($drive.Root)." -Level "INFO"
            }
        } catch {
            Write-EnhancedLog -Message "An error occurred during disk space check: $_" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_
        }
    }

    end {
        Write-EnhancedLog -Message "Check-DiskSpace function execution completed." -Level "INFO"
    }
}
#EndRegion '.\Private\Check-DiskSpace.ps1' 35
#Region '.\Private\Handle-RobocopyExitCode.ps1' -1

function Handle-RobocopyExitCode {
    <#
    .SYNOPSIS
    Handles the exit code from a Robocopy operation.
 
    .DESCRIPTION
    The Handle-RobocopyExitCode function interprets the exit code returned by a Robocopy operation and logs an appropriate message. The exit codes provide information about the success or failure of the operation and any additional conditions encountered.
 
    .PARAMETER ExitCode
    The exit code returned by Robocopy.
 
    .EXAMPLE
    Handle-RobocopyExitCode -ExitCode 0
    Logs a message indicating no files were copied, no files were mismatched, and no failures were encountered.
 
    .EXAMPLE
    Handle-RobocopyExitCode -ExitCode 1
    Logs a message indicating all files were copied successfully.
 
    .NOTES
    This function is typically used internally after executing a Robocopy command to handle and log the exit status.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [int]$ExitCode
    )

    begin {
        Write-EnhancedLog -Message "Starting Handle-RobocopyExitCode function" -Level "INFO"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    process {
        try {
            switch ($ExitCode) {
                0 { Write-EnhancedLog -Message "No files were copied. No files were mismatched. No failures were encountered." -Level "INFO" }
                1 { Write-EnhancedLog -Message "All files were copied successfully." -Level "INFO" }
                2 { Write-EnhancedLog -Message "There are some additional files in the destination directory that are not present in the source directory. No files were copied." -Level "INFO" }
                3 { Write-EnhancedLog -Message "Some files were copied. Additional files were present. No failure was encountered." -Level "INFO" }
                4 { Write-EnhancedLog -Message "Some files were mismatched. No files were copied." -Level "INFO" }
                5 { Write-EnhancedLog -Message "Some files were copied. Some files were mismatched. No failure was encountered." -Level "INFO" }
                6 { Write-EnhancedLog -Message "Additional files and mismatched files exist. No files were copied." -Level "INFO" }
                7 { Write-EnhancedLog -Message "Files were copied, a file mismatch was present, and additional files were present." -Level "INFO" }
                8 { Write-EnhancedLog -Message "Several files did not copy." -Level "ERROR" }
                default { Write-EnhancedLog -Message "Robocopy failed with exit code $ExitCode" -Level "ERROR" }
            }
        }
        catch {
            Write-EnhancedLog -Message "An error occurred while handling the Robocopy exit code: $_" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_
        }
    }

    end {
        Write-EnhancedLog -Message "Handle-RobocopyExitCode function execution completed." -Level "INFO"
    }
}
#EndRegion '.\Private\Handle-RobocopyExitCode.ps1' 61
#Region '.\Private\Test-Directory.ps1' -1

function Test-Directory {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]$Path
    )

    begin {
        Write-EnhancedLog -Message "Starting Test-Directory function" -Level "INFO"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    process {
        try {
            if (-Not (Test-Path -Path $Path -PathType Container)) {
                Write-EnhancedLog -Message "The path '$Path' is not a valid directory." -Level "ERROR"
                throw "The path '$Path' is not a valid directory."
            } else {
                Write-EnhancedLog -Message "The path '$Path' is a valid directory." -Level "INFO"
            }
        } catch {
            Write-EnhancedLog -Message "An error occurred during directory validation: $_" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_
        }
    }

    end {
        Write-EnhancedLog -Message "Test-Directory function execution completed." -Level "INFO"
    }
}
#EndRegion '.\Private\Test-Directory.ps1' 32
#Region '.\Private\Test-Robocopy.ps1' -1


function Test-Robocopy {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false)]
        [string]$RobocopyPath = "C:\Windows\System32\Robocopy.exe"
    )

    begin {
        Write-EnhancedLog -Message "Starting Test-Robocopy function" -Level "INFO"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    process {
        try {
            if (-Not (Test-Path -Path $RobocopyPath)) {
                Write-EnhancedLog -Message "Robocopy.exe is not available at the specified path: $RobocopyPath" -Level "ERROR"
                throw "Robocopy.exe is not available at the specified path: $RobocopyPath"
            }
            else {
                Write-EnhancedLog -Message "Robocopy.exe is available at the specified path: $RobocopyPath" -Level "INFO"
            }
        }
        catch {
            Write-EnhancedLog -Message "An error occurred during Robocopy availability check: $_" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_
        }
    }

    end {
        Write-EnhancedLog -Message "Test-Robocopy function execution completed." -Level "INFO"
    }
}
#EndRegion '.\Private\Test-Robocopy.ps1' 35
#Region '.\Public\Copy-FilesToPathWithKill.ps1' -1

function Copy-FilesToPathWithKill {
    <#
    .SYNOPSIS
    Copies all files and folders in the specified source directory to the specified destination path, and kills any processes that lock files preventing the copy operation.
 
    .DESCRIPTION
    This function copies all files and folders located in the specified source directory to the specified destination path. If any files are locked by other processes, the function identifies and kills those processes, then retries the copy operation.
 
    .PARAMETER SourcePath
    The source path from where the files and folders will be copied.
 
    .PARAMETER DestinationPath
    The destination path where the files and folders will be copied.
 
    .EXAMPLE
    Copy-FilesToPathWithKill -SourcePath "C:\Source" -DestinationPath "C:\Temp"
 
    This example copies all files and folders in the "C:\Source" directory to the "C:\Temp" directory.
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$SourcePath,

        [Parameter(Mandatory = $true)]
        [string]$DestinationPath
    )

    Begin {
        Write-EnhancedLog -Message "Starting the copy process from the Source Path $SourcePath to $DestinationPath" -Level "INFO"
        Log-Params -Params @{
            SourcePath = $SourcePath
            DestinationPath = $DestinationPath
        }

        # Ensure the destination directory exists
        if (-not (Test-Path -Path $DestinationPath)) {
            New-Item -Path $DestinationPath -ItemType Directory | Out-Null
        }
    }

    Process {
        try {
            # Attempt the copy operation
            $copyParams = @{
                Path        = "$SourcePath\*"
                Destination = $DestinationPath
                Recurse     = $true
                Force       = $true
                ErrorAction = "Stop"
            }
            Copy-Item @copyParams

            Write-EnhancedLog -Message "All items copied successfully from the Source Path $SourcePath to $DestinationPath." -Level "INFO"
        }
        catch {
            Write-EnhancedLog -Message "Error occurred during the copy process: $_" -Level "ERROR"
            Handle-Error -ErrorRecord $_

            # Check if the error is due to a file being in use by another process
            if ($_.Exception -match "because it is being used by another process") {
                Write-EnhancedLog -Message "Attempting to find and kill the process locking the file." -Level "WARNING"
                try {
                    # Find the process locking the file
                    $lockedFile = $_.Exception.Message -match "'(.+?)'" | Out-Null
                    $lockedFile = $matches[1]

                    $lockingProcesses = Get-Process | Where-Object { $_.Modules | Where-Object { $_.FileName -eq $lockedFile } }

                    foreach ($process in $lockingProcesses) {
                        Write-EnhancedLog -Message "Killing process $($process.Id) locking the file $lockedFile" -Level "INFO"
                        Stop-Process -Id $process.Id -Force -Confirm:$false
                    }

                    # Retry the copy operation
                    Copy-Item @copyParams
                    Write-EnhancedLog -Message "Copy operation retried and succeeded." -Level "INFO"
                }
                catch {
                    Write-EnhancedLog -Message "Failed to find or kill the process locking the file: $lockedFile" -Level "ERROR"
                    Handle-Error -ErrorRecord $_
                }
            }
        }
    }

    End {
        Write-EnhancedLog -Message "Copy process completed." -Level "INFO"
    }
}



# Copy-FilesToPathWithKill -SourcePath "C:\Source" -DestinationPath "C:\Temp"
#EndRegion '.\Public\Copy-FilesToPathWithKill.ps1' 95
#Region '.\Public\Copy-FilesWithRobocopy.ps1' -1

function Copy-FilesWithRobocopy {
    <#
    .SYNOPSIS
    Copies files from a source directory to a destination directory using Robocopy.
 
    .DESCRIPTION
    The Copy-FilesWithRobocopy function copies files from a source directory to a destination directory based on a specified file pattern. It uses Robocopy to perform the file copy operation. The function includes validation of the source and destination directories, disk space checks, and logs the Robocopy process.
 
    .PARAMETER Source
    The source directory from which files will be copied.
 
    .PARAMETER Destination
    The destination directory to which files will be copied.
 
    .PARAMETER FilePattern
    The file pattern to match files that should be copied.
 
    .PARAMETER RetryCount
    The number of retries if a copy fails. Default is 2.
 
    .PARAMETER WaitTime
    The wait time between retries in seconds. Default is 5.
 
    .PARAMETER RequiredSpaceGB
    The required free space in gigabytes at the destination. Default is 10 GB.
 
    .PARAMETER Exclude
    The directories or files to exclude from the copy operation.
 
    .EXAMPLE
    Copy-FilesWithRobocopy -Source "C:\Source" -Destination "C:\Destination" -FilePattern "*.txt"
    Copies all .txt files from C:\Source to C:\Destination.
 
    .EXAMPLE
    "*.txt", "*.log" | Copy-FilesWithRobocopy -Source "C:\Source" -Destination "C:\Destination"
    Copies all .txt and .log files from C:\Source to C:\Destination using pipeline input for the file patterns.
 
    .EXAMPLE
    Copy-FilesWithRobocopy -Source "C:\Source" -Destination "C:\Destination" -Exclude ".git"
    Copies files from C:\Source to C:\Destination excluding the .git folder.
 
    .NOTES
    This function relies on the following private functions:
    - Check-DiskSpace.ps1
    - Handle-RobocopyExitCode.ps1
    - Test-Directory.ps1
    - Test-Robocopy.ps1
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Source,
        [Parameter(Mandatory = $true)]
        [string]$Destination,
        [Parameter(Mandatory = $false, ValueFromPipeline = $true)]
        [string]$FilePattern,
        [Parameter(Mandatory = $false)]
        [int]$RetryCount = 2,
        [Parameter(Mandatory = $false)]
        [int]$WaitTime = 5,
        [Parameter(Mandatory = $false)]
        [int]$RequiredSpaceGB = 10, # Example value for required space
        [Parameter(Mandatory = $false)]
        [string[]]$Exclude
    )

    begin {
        Write-EnhancedLog -Message "Starting Copy-FilesWithRobocopy function" -Level "INFO"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters

        # Validate Robocopy, source and destination directories once
        Test-Robocopy
        Test-Directory -Path $Source
        Write-EnhancedLog -Message "Validated source directory: $Source" -Level "INFO"

        Test-Directory -Path $Destination
        Write-EnhancedLog -Message "Validated destination directory: $Destination" -Level "INFO"

        # Check disk space once
        Check-DiskSpace -Path $Destination -RequiredSpaceGB $RequiredSpaceGB

        # Prepare Robocopy log file path
        $timestamp = Get-Date -Format "yyyyMMddHHmmss"
        $logFilePath = "$env:TEMP\RobocopyLog_$timestamp.log"
        Write-EnhancedLog -Message "Robocopy log file will be saved to: $logFilePath" -Level "INFO"
    }

    process {
        try {
            $robocopyPath = "C:\Windows\System32\Robocopy.exe"
            $robocopyArgs = @(
                $Source, 
                $Destination, 
                $FilePattern, 
                "/E", 
                "/R:$RetryCount", 
                "/W:$WaitTime",
                "/LOG:$logFilePath"
            )

            # Add exclude arguments if provided
            if ($Exclude) {
                $excludeDirs = $Exclude | ForEach-Object { "/XD $_" }
                $excludeFiles = $Exclude | ForEach-Object { "/XF $_" }
                $robocopyArgs = $robocopyArgs + $excludeDirs + $excludeFiles

                # Log what is being excluded
                foreach ($item in $Exclude) {
                    Write-EnhancedLog -Message "Excluding: $item" -Level "INFO"
                }
            }

            Write-EnhancedLog -Message "Starting Robocopy process with arguments: $robocopyArgs" -Level "INFO"
            # Splatting Start-Process parameters
            $startProcessParams = @{
                FilePath     = $robocopyPath
                ArgumentList = $robocopyArgs
                NoNewWindow  = $true
                Wait         = $true
                PassThru     = $true
            }

            $process = Start-Process @startProcessParams

            Handle-RobocopyExitCode -ExitCode $process.ExitCode
        }
        catch {
            Write-EnhancedLog -Message "An error occurred while copying files with Robocopy: $_" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_
        }
    }

    end {
        Write-EnhancedLog -Message "Copy-FilesWithRobocopy function execution completed." -Level "INFO"
    }
}
#EndRegion '.\Public\Copy-FilesWithRobocopy.ps1' 139
#Region '.\Public\Copy-FileToPublicAndTemp.ps1' -1

function Copy-FileToPublicAndTemp {
    <#
    .SYNOPSIS
    Copies a specified file to the public desktop and C:\temp, making it available to all users and in the temp directory.
 
    .DESCRIPTION
    This function copies a specified file to the public desktop and C:\temp, ensuring it is available to all users and also in the temp directory. Enhanced logging is used for feedback and error handling.
 
    .PARAMETER SourceFilePath
    The path of the file to be copied.
 
    .EXAMPLE
    Copy-FileToPublicAndTemp -SourceFilePath "C:\Path\To\fcremove.exe"
 
    This example copies the file "fcremove.exe" to the public desktop and C:\temp, making it available to all users and in the temp directory.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$SourceFilePath
    )

    begin {
        Write-EnhancedLog -Message 'Starting Copy-FileToPublicAndTemp function' -Level 'INFO'
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    process {
        try {
            if (-not (Test-Path -Path $SourceFilePath)) {
                Write-EnhancedLog -Message "Source file not found: $SourceFilePath" -Level "ERROR"
                throw "Source file not found: $SourceFilePath"
            }

            # Define the destination paths
            $publicDesktopPath = 'C:\Users\Public\Desktop'
            $tempPath = 'C:\temp'

            # Ensure the public desktop directory exists
            $publicDesktopParams = @{
                Path      = $publicDesktopPath
                ItemType  = 'Directory'
                Force     = $true
                ErrorAction = 'Stop'
            }
            if (-not (Test-Path -Path $publicDesktopPath)) {
                Write-EnhancedLog -Message "Public desktop path not found. Creating directory." -Level "INFO"
                New-Item @publicDesktopParams | Out-Null
            }

            # Ensure the temp directory exists
            $tempParams = @{
                Path      = $tempPath
                ItemType  = 'Directory'
                Force     = $true
                ErrorAction = 'Stop'
            }
            if (-not (Test-Path -Path $tempPath)) {
                Write-EnhancedLog -Message "Temp path not found. Creating directory." -Level "INFO"
                New-Item @tempParams | Out-Null
            }

            # Copy the file to the public desktop
            $destinationFilePathPublic = Join-Path -Path $publicDesktopPath -ChildPath (Split-Path -Leaf $SourceFilePath)
            $copyParamsPublic = @{
                Path        = $SourceFilePath
                Destination = $destinationFilePathPublic
                Force       = $true
                ErrorAction = 'Stop'
            }
            Write-EnhancedLog -Message "Copying file to: $destinationFilePathPublic" -Level "INFO"
            Copy-Item @copyParamsPublic
            Write-EnhancedLog -Message "File copied to: $destinationFilePathPublic" -Level "INFO"

            # Copy the file to the temp directory
            $destinationFilePathTemp = Join-Path -Path $tempPath -ChildPath (Split-Path -Leaf $SourceFilePath)
            $copyParamsTemp = @{
                Path        = $SourceFilePath
                Destination = $destinationFilePathTemp
                Force       = $true
                ErrorAction = 'Stop'
            }
            Write-EnhancedLog -Message "Copying file to: $destinationFilePathTemp" -Level "INFO"
            Copy-Item @copyParamsTemp
            Write-EnhancedLog -Message "File copied to: $destinationFilePathTemp" -Level "INFO"

        } catch {
            Write-EnhancedLog -Message "An error occurred while copying the file: $_" -Level "ERROR"
            Handle-Error -ErrorRecord $_
        }
    }

    end {
        Write-EnhancedLog -Message 'Copy-FileToPublicAndTemp function completed' -Level 'INFO'
    }
}
#EndRegion '.\Public\Copy-FileToPublicAndTemp.ps1' 98
#Region '.\Public\Copy-ItemWithRobocopy.ps1' -1

function Copy-ItemsWithRobocopy {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$SourcePath,

        [Parameter(Mandatory = $true)]
        [string]$DestinationPath
    )

    Begin {
        Write-EnhancedLog -Message "Starting Copy-ItemsWithRobocopy function" -Level "INFO"
        Log-Params -Params @{
            SourcePath = $SourcePath
            DestinationPath = $DestinationPath
        }

        # Ensure the destination directory 'DownloadsBackup' exists
        $finalDestinationPath = Join-Path -Path $DestinationPath -ChildPath "DownloadsBackup"
        if (-not (Test-Path -Path $finalDestinationPath)) {
            New-Item -ItemType Directory -Force -Path $finalDestinationPath | Out-Null
        }
    }

    Process {
        try {
            # Use Robocopy for copying. /E is for copying subdirectories including empty ones. /R:0 and /W:0 are for no retries and no wait between retries.
            # Ensure to add a trailing backslash to the source path to copy its contents
            $robocopyArgs = @("${SourcePath}\", $finalDestinationPath, "/E", "/R:0", "/W:0")

            $result = robocopy @robocopyArgs
            switch ($LASTEXITCODE) {
                0 { Write-EnhancedLog -Message "No files were copied. No files were mismatched. No failures were encountered." -Level "INFO" }
                1 { Write-EnhancedLog -Message "All files were copied successfully." -Level "INFO" }
                2 { Write-EnhancedLog -Message "There are some additional files in the destination directory that are not present in the source directory. No files were copied." -Level "INFO" }
                3 { Write-EnhancedLog -Message "Some files were copied. Additional files were present. No failure was encountered." -Level "INFO" }
                4 { Write-EnhancedLog -Message "Some files were mismatched. No files were copied." -Level "INFO" }
                5 { Write-EnhancedLog -Message "Some files were copied. Some files were mismatched. No failure was encountered." -Level "INFO" }
                6 { Write-EnhancedLog -Message "Additional files and mismatched files exist. No files were copied." -Level "INFO" }
                7 { Write-EnhancedLog -Message "Files were copied, a file mismatch was present, and additional files were present." -Level "INFO" }
                8 { Write-EnhancedLog -Message "Several files did not copy." -Level "ERROR" }
                default { Write-EnhancedLog -Message "Robocopy failed with exit code $LASTEXITCODE" -Level "ERROR" }
            }
        } catch {
            Write-EnhancedLog -Message "An error occurred in Copy-ItemsWithRobocopy function: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Copy-ItemsWithRobocopy function" -Level "INFO"
    }
}
#EndRegion '.\Public\Copy-ItemWithRobocopy.ps1' 54
#Region '.\Public\Validate-FileExists.ps1' -1

function Validate-FileExists {
    param (
        [Parameter(Mandatory = $true)]
        [string]$FilePath
    )

    if (-Not (Test-Path -Path $FilePath)) {
        Write-EnhancedLog -Message "File '$FilePath' does not exist." -Level "ERROR"
        throw "File '$FilePath' does not exist."
    }
}


#EndRegion '.\Public\Validate-FileExists.ps1' 14
#Region '.\Public\Verify-CopyOperation.ps1' -1

function Verify-CopyOperation {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$SourcePath,

        [Parameter(Mandatory = $true)]
        [string]$DestinationPath
    )

    begin {
        Write-EnhancedLog -Message "Verifying copy operation..." -Level "INFO"
        Log-Params -Params @{
            SourcePath = $SourcePath
            DestinationPath = $DestinationPath
        }

        $sourceItems = Get-ChildItem -Path $SourcePath -Recurse
        $destinationItems = Get-ChildItem -Path $DestinationPath -Recurse

        # Use a generic list for better performance compared to using an array with +=
        $verificationResults = New-Object System.Collections.Generic.List[Object]
    }

    process {
        try {
            foreach ($item in $sourceItems) {
                $relativePath = $item.FullName.Substring($SourcePath.Length)
                $correspondingPath = Join-Path -Path $DestinationPath -ChildPath $relativePath

                if (-not (Test-Path -Path $correspondingPath)) {
                    $verificationResults.Add([PSCustomObject]@{
                            Status       = "Missing"
                            SourcePath   = $item.FullName
                            ExpectedPath = $correspondingPath
                        })
                }
            }

            foreach ($item in $destinationItems) {
                $relativePath = $item.FullName.Substring($DestinationPath.Length)
                $correspondingPath = Join-Path -Path $SourcePath -ChildPath $relativePath

                if (-not (Test-Path -Path $correspondingPath)) {
                    $verificationResults.Add([PSCustomObject]@{
                            Status     = "Extra"
                            SourcePath = $correspondingPath
                            ActualPath = $item.FullName
                        })
                }
            }
        }
        catch {
            Write-EnhancedLog -Message "Error during verification process: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
        }
    }

    end {
        if ($verificationResults.Count -gt 0) {
            Write-EnhancedLog -Message "Discrepancies found. See detailed log." -Level "WARNING"
            $verificationResults | Format-Table -AutoSize | Out-String | ForEach-Object { 
                Write-EnhancedLog -Message $_ -Level "INFO" 
            }

            #Uncomment when troubelshooting
            $verificationResults | Out-GridView
        }
        else {
            Write-EnhancedLog -Message "All items verified successfully. No discrepancies found." -Level "INFO"
        }

        Write-EnhancedLog -Message ("Total items in source: " + $sourceItems.Count) -Level "INFO"
        Write-EnhancedLog -Message ("Total items in destination: " + $destinationItems.Count) -Level "INFO"
    }
}


# # Define the source and destination paths
# $sourcePath = "C:\Source"
# $destinationPath = "C:\Destination"

# # Example usage of the Verify-CopyOperation function
# Verify-CopyOperation -SourcePath $sourcePath -DestinationPath $destinationPath

#EndRegion '.\Public\Verify-CopyOperation.ps1' 86