Powershell/Public/Start-Reversion.ps1

Function Start-Reversion {
    <#
    .SYNOPSIS
        Reverts a user migration by restoring original registry files for a specified Windows SID.
 
    .DESCRIPTION
        This function reverts a user migration by:
        1. Looking up the account SID in the Windows registry ProfileList
        2. Identifying the .ADMU profile path
        3. Restoring original NTUSER.DAT and UsrClass.dat files from backups
        4. Preserving migrated files with _migrated suffix for rollback purposes
 
    .PARAMETER UserSID
        The Windows Security Identifier (SID) of the user account to revert.
 
    .PARAMETER TargetProfileImagePath
        The actual profile path to revert. If not specified, will use the path from the registry.
        This path will be validated to ensure it exists and is associated with the UserSID.
 
    .PARAMETER DryRun
        Shows what actions would be performed without actually executing them.
 
    .PARAMETER Force
        Bypasses confirmation prompts and forces the revert operation.
 
    .EXAMPLE
        Start-Reversion -UserSID "S-1-5-21-123456789-1234567890-123456789-1001"
        Reverts the migration for the specified user SID using the registry profile path.
 
    .EXAMPLE
        Start-Reversion -UserSID "S-1-5-21-123456789-1234567890-123456789-1001" -TargetProfileImagePath "C:\Users\john.doe"
        Reverts the migration using a specific target profile path instead of the registry value.
 
    .EXAMPLE
        Start-Reversion -UserSID "S-1-5-21-123456789-1234567890-123456789-1001" -DryRun
        Shows what would be reverted without making actual changes.
 
    .OUTPUTS
        [PSCustomObject] Returns revert operation results with success status and details.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory = $true, Position = 0)]
        [ValidatePattern("^S-\d-\d+-(\d+-){1,14}\d+$")]
        [string]$UserSID,

        [Parameter(Mandatory = $false, Position = 1)]
        [ValidateScript({
                if (Test-Path $_ -PathType Container) { $true }
                else { throw "Target profile path does not exist: $_" }
            })]
        [string]$TargetProfileImagePath,
        [Parameter(Mandatory = $false)]
        [bool]$form = $false,
        [Parameter(Mandatory = $false)]
        [string]$UserName,
        [Parameter(Mandatory = $false)]
        [string]$ProfileSize,
        [Parameter(Mandatory = $false)]
        [string]$LocalPath,
        [Parameter(Mandatory = $false)]
        [switch]$DryRun,
        [Parameter(Mandatory = $false)]
        [switch]$Force
    )

    Begin {
        Write-ToLog -Message "Begin Revert Migration" -MigrationStep -Level Info

        # Initialize result object
        $revertResult = [PSCustomObject]@{
            Success             = $false
            UserSID             = $UserSID
            RegistryProfilePath = $null
            TargetProfilePath   = $TargetProfileImagePath
            ActualProfilePath   = $null
            FilesReverted       = @()
            Errors              = @()
            StartTime           = Get-Date
            EndTime             = $null
            WhatIfMode          = $DryRun.IsPresent
            RegistryUpdated     = $false
        }
        $account = New-Object System.Security.Principal.SecurityIdentifier($UserSID)
        $domainUser = ($account.Translate([System.Security.Principal.NTAccount])).Value

        # Regex pattern to identify .ADMU profile paths
        $admuPathPattern = '\.ADMU$'

        Write-ToLog -Message "Validating user SID: $UserSID" -Level Verbose -Step "Revert-Migration"

        # Status message map for reversion steps
        $revertMessageMap = [Ordered]@{
            revertInit                  = @{
                step = "Initializing"
                desc = "Initializing the profile reversion process."
            }
            revertValidateProfilePath   = @{
                step = "Validating Profile Registry Path"
                desc = "Validating the profile path exists in the registry."
            }
            revertValidateACLBackups    = @{
                step = "Validating ACL Backups"
                desc = "Verifying that valid ACL backups exist before proceeding."
            }
            revertValidateRegistryFiles = @{
                step = "Validating Registry Files"
                desc = "Validating the integrity of the registry files to be reverted."
            }
            revertRegistryFiles         = @{
                step = "Restoring Registry Files"
                desc = "Restoring the original registry files."
            }
            revertProfileImagePath      = @{
                step = "Restoring ProfileImagePath"
                desc = "Restoring the ProfileImagePath value in the registry."
            }
            revertProfileACLs           = @{
                step = "Restoring Profile ACLs"
                desc = "Restoring the profile Access Control Lists (ACLs) from backup."
            }
            revertTakeOwnership         = @{
                step = "Taking Ownership"
                desc = "Taking ownership of the profile directory."
            }
            revertRemoveJCUserArtifacts = @{
                step = "Removing JumpCloud Artifacts"
                desc = "Removing JumpCloud user artifacts created during the initial process."
            }
            revertComplete              = @{
                step = "Reversion Complete"
                desc = "Profile Reversion completed successfully."
            }
        }


        $profileSize = Get-ProfileSize -ProfilePath $LocalPath

        # Prefer the progress form created in Form.ps1 so updates apply to the first window the user sees
        if ((-not $script:ProgressBar) -and ($form)) {
            $script:ProgressBar = New-ProgressForm
        }
    }

    Process {
        try {
            #region Validate Registry and Determine Profile Path
            Write-ToLog -Message "Looking up profile information for SID: $UserSID" -Level Info -Step "Revert-Migration"
            # Casing fixed to 'revertInit'
            Write-ToProgress -form $form -Status "revertInit" -ProgressBar $ProgressBar -ProfileSize $profileSize -LocalPath $LocalPath -StatusMap $revertMessageMap

            # Get profile information from registry for validation
            $profileRegistryPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$UserSID"

            # Casing fixed to 'revertValidateProfilePath', removed -StatusType, added -StatusMap
            Write-ToProgress -form $form -Status "revertValidateProfilePath" -ProgressBar $ProgressBar -StatusMap $revertMessageMap
            if (-not (Test-Path $profileRegistryPath)) {
                throw "Profile registry path not found for SID: $UserSID"
            }

            $registryProfileImagePath = (Get-ItemProperty -Path $profileRegistryPath -Name "ProfileImagePath" -ErrorAction Stop).ProfileImagePath
            $revertResult.RegistryProfilePath = $registryProfileImagePath

            Write-ToLog -Message "Found registry profile path: $registryProfileImagePath" -Level Info -Step "Revert-Migration"

            # Validate this is an ADMU migrated profile by checking registry path
            if ($registryProfileImagePath -notmatch $admuPathPattern) {
                throw "Registry profile path does not contain .ADMU suffix. This does not appear to be a migrated profile: $registryProfileImagePath"
            }

            Write-ToLog -Message "Confirmed .ADMU migration profile detected in registry" -Level Verbose -Step "Revert-Migration"

            # Determine which profile path to use
            if ($TargetProfileImagePath) {
                Write-ToLog -Message "Using provided target profile path: $TargetProfileImagePath" -Level Info -Step "Revert-Migration"
                $profileImagePath = $TargetProfileImagePath

                # Validate target profile path is associated with the UserSID
                $sidValidation = Confirm-ProfileSidAssociation -ProfilePath $TargetProfileImagePath -UserSID $UserSID
                if (-not $sidValidation.IsValid) {
                    throw "Target profile path validation failed: $($sidValidation.Reason)"
                }
                Write-ToLog -Message "Target profile path validated for UserSID: $UserSID" -Level Verbose -Step "Revert-Migration"
            } else {
                # Use registry path, remove .ADMU suffix
                $profileImagePath = $registryProfileImagePath -replace $admuPathPattern, ''
                $sidValidation = Confirm-ProfileSidAssociation -ProfilePath $profileImagePath -UserSID $UserSID
                if (-not $sidValidation.IsValid) {
                    throw "Registry profile path validation failed: $($sidValidation.Reason)"
                }
                Write-ToLog -Message "Using registry profile path (without .ADMU): $profileImagePath" -Level Info -Step "Revert-Migration"
            }

            $revertResult.ActualProfilePath = $profileImagePath
            #endregion Validate Registry and Determine Profile Path

            #region Validate Profile Directory
            if (-not (Test-Path $profileImagePath -PathType Container)) {
                throw "Profile directory does not exist: $profileImagePath"
            }

            Write-ToLog -Message "Profile directory exists and is accessible" -Level Verbose -Step "Revert-Migration"
            Write-ToLog -Message "Profile path: $profileImagePath" -Level Verbose -Step "Revert-Migration"
            #endregion Validate Profile Directory

            #region Validate ProfileImagePath ACL Backup in $profileImagePath\AppData\Local\JumpCloudADMU
            # Casing fixed to 'revertValidateACLBackups', removed -StatusType, added -StatusMap
            Write-ToProgress -form $form -Status "revertValidateACLBackups" -ProgressBar $ProgressBar -StatusMap $revertMessageMap
            # Regex pattern to identify ACL backup files: S-1-12-1-3466645622-1152519358-2404555438-459629385_permission_backup_20251117-1353
            $aclBackupPattern = "^{0}_permission_backup_\d{{8}}-\d{{4}}$" -f [Regex]::Escape($UserSID)
            $aclBackupDir = Join-Path -Path $profileImagePath -ChildPath "AppData\Local\JumpCloudADMU"
            $aclBackupFiles = @()
            if (Test-Path -Path $aclBackupDir -PathType Container) {
                $aclBackupFiles = Get-ChildItem -Path $aclBackupDir -File | Where-Object { $_.Name -match $aclBackupPattern }
            }
            $latestAclBackupFile = $aclBackupFiles | Sort-Object LastWriteTime -Descending | Select-Object -First 1
            # Get the most recent ACL backup file path

            if ($aclBackupFiles.Count -eq 0) {
                Throw "No ACL backup files found in directory: $aclBackupDir for SID: $UserSID. Cannot proceed with revert."
            } else {
                Write-ToLog -Message "Found ACL backup files in $aclBackupDir" -Level Info -Step "Revert-Migration"
            }
            #endregion Validate ProfileImagePath ACL Backup

            #region Identify Registry Files to Revert
            $registryFiles = @()

            # NTUSER.DAT files in profile root
            $ntuserCurrent = Join-Path $profileImagePath "NTUSER.DAT"
            $ntuserOriginalFiles = Get-ChildItem -Path $profileImagePath -Force | Where-Object { $_.Name -match "NTUSER_original_*" }

            if ($ntuserOriginalFiles.Count -eq 0) {
                Write-ToLog -Message "Warning: No original NTUSER.DAT backup found in $profileImagePath" -Level Warning -Step "Revert-Migration"
            } else {
                $ntuserOriginal = $ntuserOriginalFiles | Sort-Object LastWriteTime -Descending | Select-Object -First 1
                $ntuserMigrated = $ntuserCurrent -replace '\.DAT$', '_migrated.DAT'

                $registryFiles += [PSCustomObject]@{
                    Type         = "NTUSER"
                    CurrentFile  = $ntuserCurrent
                    OriginalFile = $ntuserOriginal.FullName
                    MigratedFile = $ntuserMigrated
                    Location     = "Profile Root"

                }

                Write-ToLog -Message "Found NTUSER original backup: $($ntuserOriginal.Name)" -Level Info -Step "Revert-Migration"
            }
            # Validate that the UsrClass and NTUSER original files were found
            if ($registryFiles.Type -notcontains "NTUSER") {
                Throw "No NTUser.DAT backup files found in directory: $profileImagePath for SID: $UserSID. Cannot proceed with revert."
            }

            # UsrClass.dat files in AppData
            $appDataPath = Join-Path $profileImagePath "AppData\Local\Microsoft\Windows"
            $usrClassCurrent = Join-Path $appDataPath "UsrClass.dat"
            $usrClassOriginalPattern = Join-Path $appDataPath "UsrClass_original_*.dat"
            $usrClassOriginalFiles = Get-ChildItem -Path $usrClassOriginalPattern -Force | Where-Object { $_.Name -match "UsrClass_original_*" }

            if ($usrClassOriginalFiles.Count -eq 0) {
                Write-ToLog -Message "Warning: No original UsrClass.dat backup found in $appDataPath" -Level Warning -Step "Revert-Migration"
            } else {
                $usrClassOriginal = $usrClassOriginalFiles | Sort-Object LastWriteTime -Descending | Select-Object -First 1
                $usrClassMigrated = $usrClassCurrent -replace '\.dat$', '_migrated.dat'

                $registryFiles += [PSCustomObject]@{
                    Type         = "UsrClass"
                    CurrentFile  = $usrClassCurrent
                    OriginalFile = $usrClassOriginal.FullName
                    MigratedFile = $usrClassMigrated
                    Location     = "AppData"
                }

                Write-ToLog -Message "Found UsrClass original backup: $($usrClassOriginal.Name)" -Level Info -Step "Revert-Migration"
            }

            if ($registryFiles.Type -notcontains "UsrClass") {
                Throw "No UsrClass.dat backup files found in directory: $profileImagePath for SID: $UserSID. Cannot proceed with revert."
            }
            #endregion Identify Registry Files to Revert

            #region Validate Files Before Revert
            # Casing fixed to 'revertValidateRegistryFiles', removed -StatusType, added -StatusMap
            Write-ToProgress -form $form -Status "revertValidateRegistryFiles" -ProgressBar $ProgressBar -StatusMap $revertMessageMap
            Write-ToLog -Message "Validating registry files before revert operation" -Level Info -Step "Revert-Migration"

            foreach ($regFile in $registryFiles) {
                # Check if original backup exists
                if (-not (Test-Path $regFile.OriginalFile)) {
                    throw "Original backup file not found: $($regFile.OriginalFile)"
                }

                # Check if current file exists
                if (-not (Test-Path $regFile.CurrentFile)) {
                    Write-ToLog -Message "Warning: Current $($regFile.Type) file not found: $($regFile.CurrentFile)" -Level Warning -Step "Revert-Migration"
                }

                Write-ToLog -Message "Validated $($regFile.Type) files in $($regFile.Location)" -Level Verbose -Step "Revert-Migration"
            }
            #endregion Validate Files Before Revert

            #region Confirmation Prompt
            if (-not $Force -and -not $DryRun) {
                Write-ToLog -Message "Requesting user confirmation for revert operation" -Level Info -Step "Revert-Migration"

                Write-Host "`nADMU Migration Revert Summary:" -ForegroundColor Yellow
                Write-Host " User SID: $UserSID" -ForegroundColor White
                Write-Host " Registry Profile Path: $registryProfileImagePath" -ForegroundColor White
                Write-Host " Target Profile Path: $profileImagePath" -ForegroundColor White
                Write-Host " Registry Files to Revert: $($registryFiles.Count)" -ForegroundColor White

                foreach ($regFile in $registryFiles) {
                    Write-Host " - $($regFile.Type) ($($regFile.Location))" -ForegroundColor Gray
                    Write-Host " Current: $($regFile.CurrentFile)" -ForegroundColor DarkGray
                    Write-Host " Backup: $($regFile.OriginalFile)" -ForegroundColor DarkGray
                }
                Write-Host "`nWARNING: This operation will overwrite the current registry files with the original backups and change the ownership of the profile directory to $domainUser." -ForegroundColor Red
                $confirmation = Read-Host "`nDo you want to proceed with the revert? (y/N)"
                if ($confirmation -notmatch '^[Yy]([Ee][Ss])?$') {
                    Write-ToLog -Message "Revert operation cancelled by user" -Level Info -Step "Revert-Migration"
                    $revertResult.Errors += "Operation cancelled by user"
                    return $revertResult
                }
            }
            #endregion Confirmation Prompt

            #region Perform Registry File Revert
            # Casing fixed to 'revertRegistryFiles', removed -StatusType, added -StatusMap
            Write-ToProgress -form $form -Status "revertRegistryFiles" -ProgressBar $ProgressBar -StatusMap $revertMessageMap
            Write-ToLog -Message "Beginning registry file revert operations" -Level Info -Step "Revert-Migration"

            foreach ($regFile in $registryFiles) {
                try {
                    Write-ToLog -Message "Processing $($regFile.Type) files in $($regFile.Location)" -Level Info -Step "Revert-Migration"

                    if ($DryRun) {
                        Write-Host "WHAT IF: Would rename $($regFile.CurrentFile) to $($regFile.MigratedFile)" -ForegroundColor Cyan
                        Write-Host "WHAT IF: Would rename $($regFile.OriginalFile) to $($regFile.CurrentFile)" -ForegroundColor Cyan
                    } else {
                        # Step 1: Rename current file to _migrated (preserve migration state)
                        if (Test-Path $regFile.CurrentFile) {
                            Write-ToLog -Message "Renaming current $($regFile.Type) to migrated backup: $($regFile.MigratedFile)" -Level Verbose -Step "Revert-Migration"
                            Move-Item -Path $regFile.CurrentFile -Destination $regFile.MigratedFile -Force
                        }

                        # Step 2: Rename original backup to current (restore original state)
                        Write-ToLog -Message "Restoring original $($regFile.Type) file: $($regFile.CurrentFile)" -Level Verbose -Step "Revert-Migration"
                        Move-Item -Path $regFile.OriginalFile -Destination $regFile.CurrentFile -Force

                        # Verify the restore was successful
                        if (Test-Path $regFile.CurrentFile) {
                            $revertResult.FilesReverted += $regFile
                            Write-ToLog -Message "Successfully reverted $($regFile.Type) in $($regFile.Location)" -Level Info -Step "Revert-Migration"
                        } else {
                            throw "Failed to restore $($regFile.Type) file to $($regFile.CurrentFile)"
                        }
                    }

                } catch {
                    $errorMsg = "Failed to revert $($regFile.Type) files: $($_.Exception.Message)"
                    Write-ToLog -Message $errorMsg -Level Error -Step "Revert-Migration"
                    $revertResult.Errors += $errorMsg
                }
            }
            #endregion Perform Registry File Revert

            #region Update Registry ProfileImagePath
            # Casing fixed to 'revertProfileImagePath', removed -StatusType, added -StatusMap
            Write-ToProgress -form $form -Status "revertProfileImagePath" -ProgressBar $ProgressBar -StatusMap $revertMessageMap
            Write-ToLog -Message "Updating registry ProfileImagePath to point to reverted profile location" -Level Info -Step "Revert-Migration"

            try {
                if ($DryRun) {
                    Write-ToLog "WHAT IF: Would update registry ProfileImagePath from '$registryProfileImagePath' to '$profileImagePath'" -Level Verbose -Step "Revert-Migration"
                } else {
                    # Update the ProfileImagePath in the registry to point to the target profile path
                    # This informs Windows where to find the restored .DAT files
                    Write-ToLog -Message "Updating ProfileImagePath from '$registryProfileImagePath' to '$profileImagePath'" -Level Verbose -Step "Revert-Migration"

                    Set-ItemProperty -Path $profileRegistryPath -Name "ProfileImagePath" -Value $profileImagePath -Force

                    # Verify the update was successful
                    $updatedPath = (Get-ItemProperty -Path $profileRegistryPath -Name "ProfileImagePath").ProfileImagePath
                    if ($updatedPath -eq $profileImagePath) {
                        Write-ToLog -Message "Successfully updated registry ProfileImagePath to: $profileImagePath" -Level Info -Step "Revert-Migration"
                        $revertResult.RegistryUpdated = $true
                    } else {
                        throw "Registry update verification failed. Expected: '$profileImagePath', Got: '$updatedPath'"
                    }
                }
            } catch {
                $errorMsg = "Failed to update registry ProfileImagePath: $($_.Exception.Message)"
                Write-ToLog -Message $errorMsg -Level Error -Step "Revert-Migration"
                $revertResult.Errors += $errorMsg
                $revertResult.RegistryUpdated = $false
            }
            #endregion Update Registry ProfileImagePath

            #region Restore Profile ACLs
            if (-not $DryRun) {
                # Casing fixed to 'revertProfileACLs', removed -StatusType, added -StatusMap
                Write-ToProgress -form $form -Status "revertProfileACLs" -ProgressBar $ProgressBar -StatusMap $revertMessageMap
                Write-ToLog -Message "Restoring profile ACLs from backup" -Level Info -Step "Revert-Migration"
                try {
                    if ($latestAclBackupFile) {
                        $backupPath = Join-Path -Path $aclBackupDir -ChildPath $latestAclBackupFile.Name
                        Restore-ProfileACL -BackupPath $backupPath
                        Write-ToLog -Message "Successfully restored profile ACLs from: $($latestAclBackupFile.Name)" -Level Info -Step "Revert-Migration"
                    } else {
                        Write-ToLog -Message "No ACL backup file found to restore permissions." -Level Warning -Step "Revert-Migration"
                    }
                } catch {
                    $errorMsg = "Failed to restore profile ACLs: $($_.Exception.Message)"
                    Write-ToLog -Message $errorMsg -Level Error -Step "Revert-Migration"
                    $revertResult.Errors += $errorMsg
                }
            } else {
                Write-ToLog -Message "WHAT IF: Would restore profile ACLs from backup file: $($latestAclBackupFile.Name)" -Level Verbose -Step "Revert-Migration"
            }
            #endregion Restore Profile ACLs

            #region Take Ownership of Profile Directory
            if (-not $DryRun) {
                # Casing fixed to 'revertTakeOwnership', removed -StatusType, added -StatusMap
                Write-ToProgress -form $form -Status "revertTakeOwnership" -ProgressBar $ProgressBar -StatusMap $revertMessageMap
                Write-ToLog -Message "Setting ownership of profile directory: $profileImagePath" -Level Verbose -Step "Revert-Migration"

                $ACLRestoreLogPath = "$(Get-WindowsDrive)\Windows\Temp\jcAdmu_Revert_SetOwner.log"
                $logPath = "$(Get-WindowsDrive)\Windows\Temp\jcAdmu.log"
                $icaclsOwnerResult = icacls "$($profileImagePath)" /setowner $domainUser /T /C /Q 2>&1
                $icaclsOwnerResult | Out-File -FilePath $logPath -Append -Encoding utf8

                Write-ToLog -Message "End of Set Owner Log" -Level Info -Step "Revert-Migration"

                # Check if any error occurred
                if ($LASTEXITCODE -ne 0) {
                    Write-ToLog -Message "Failed to set ownership of profile directory. Check log at $ACLRestoreLogPath" -Level Warning -Step "Revert-Migration"
                } else {
                    Write-ToLog -Message "Successfully set ownership of profile directory to $domainUser" -Level Info -Step "Revert-Migration"
                }
            } else {
                Write-ToLog -Message "WHAT IF: Would take ownership of profile directory: $profileImagePath" -Level Verbose -Step "Revert-Migration"
            }
            #endregion Take Ownership of Profile Directory

            #region Remove JumpCloud ADMU Created User
            $jcUsers = Get-LocalUser | Where-Object { $_.Description -eq 'Created by JumpCloud ADMU' }
            if (-not $DryRun) {
                # Check if the user has the $profileImagePath as profile path
                foreach ($jcUser in $jcUsers) {
                    #Get the profile path of the user
                    $jcUserProfilePath = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$($jcUser.SID.Value)" -Name "ProfileImagePath" -ErrorAction Stop).ProfileImagePath
                    # Compare the profile path with the $profileImagePath
                    if ($jcUserProfilePath -eq $profileImagePath) {
                        Write-ToLog -message "Removing JumpCloud created user: $($jcUser.Name)" -Level Info -Step "Revert-Migration"
                        # Casing fixed to 'revertRemoveJCUserArtifacts', removed -StatusType, added -StatusMap
                        Write-ToProgress -form $form -Status "revertRemoveJCUserArtifacts" -ProgressBar $ProgressBar -StatusMap $revertMessageMap
                        Remove-LocalUser -Name $jcUser.Name -ErrorAction Stop
                        Write-ToLog -message "Successfully removed JumpCloud created user: $($jcUser.Name)" -Level Info -Step "Revert-Migration"
                        # Remove it from the Registry
                        $jcUserRegPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$($jcUser.SID.Value)"
                        if (Test-Path $jcUserRegPath) {
                            try {
                                Remove-Item -Path $jcUserRegPath -Recurse -Force -ErrorAction Stop
                                Write-ToLog -message "Successfully removed JumpCloud created user registry entry for SID: $($jcUser.SID.Value)" -Level Info -Step "Revert-Migration"
                            } catch {
                                $errorMsg = "Failed to remove JumpCloud created user registry entry for SID: $($jcUser.SID.Value): $($_.Exception.Message)"
                                Write-ToLog -Message $errorMsg -Level Error -Step "Revert-Migration"
                                $revertResult.Errors += $errorMsg
                            }
                        } else {
                            Write-ToLog -message "No registry entry found for JumpCloud created user SID: $($jcUser.SID.Value)" -Level Warning -Step "Revert-Migration"
                        }
                    }
                }
            } else {
                Write-ToLog -Message "WHAT IF: Would check for JumpCloud created users to remove" -Level Verbose -Step "Revert-Migration"
                foreach ($jcUser in $jcUsers) {
                    #Get the profile path of the user
                    $jcUserProfilePath = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$($jcUser.SID.Value)" -Name "ProfileImagePath" -ErrorAction Stop).ProfileImagePath
                    # Compare the profile path with the $profileImagePath
                    if ($jcUserProfilePath -eq $profileImagePath) {
                        Write-ToLog -message "WHAT IF: Would remove JumpCloud created user: $($jcUser.Name)" -Level Verbose -Step "Revert-Migration"
                    }
                }
            }
            #endregion Remove JumpCloud ADMU Created User

            #region Final Validation
            if (-not $DryRun) {
                Write-ToLog -Message "Performing post-revert validation" -Level Info -Step "Revert-Migration"

                $revertedCount = $revertResult.FilesReverted.Count
                $totalFiles = $registryFiles.Count
                $registryUpdated = $revertResult.RegistryUpdated

                if ($revertedCount -eq $totalFiles -and $registryUpdated) {
                    $revertResult.Success = $true
                    Write-ToLog -Message "Migration revert completed successfully. $revertedCount of $totalFiles registry files reverted and registry ProfileImagePath updated." -Level Info -Step "Revert-Migration"
                    # Casing fixed to 'revertComplete', removed -StatusType, added -StatusMap
                    Write-ToProgress -form $form -Status "revertComplete" -ProgressBar $ProgressBar -StatusMap $revertMessageMap
                } elseif ($revertedCount -eq $totalFiles -and -not $registryUpdated) {
                    Write-ToLog -Message "Migration revert completed with registry update error. $revertedCount of $totalFiles registry files reverted but ProfileImagePath update failed." -Level Warning -Step "Revert-Migration"
                } else {
                    Write-ToLog -Message "Migration revert completed with errors. $revertedCount of $totalFiles registry files reverted. Registry updated: $registryUpdated" -Level Warning -Step "Revert-Migration"
                }
            } else {
                Write-ToLog -Message "DryRun mode completed. No actual changes were made." -Level Info -Step "Revert-Migration"
                $revertResult.Success = $true
            }
            #endregion Final Validation

        } catch {
            $errorMsg = "Migration revert failed: $($_.Exception.Message)"
            Write-ToLog -Message $errorMsg -Level Error -Step "Revert-Migration"
            $revertResult.Errors += $errorMsg
            Write-ToProgress -ProgressBar $ProgressBar -Status $errorMsg -form $form -logLevel "Error"
        }
    }

    End {
        $revertResult.EndTime = Get-Date
        $duration = $revertResult.EndTime - $revertResult.StartTime

        Write-ToLog -Message "ADMU migration revert process completed in $($duration.TotalSeconds) seconds" -Level Info -Step "Revert-Migration"

        if ($revertResult.Success) {
            Write-ToLog -Message "Migration Revert End" -MigrationStep -Level Info
            Write-ToLog -message "Reverted UserSID: $UserSID" -Level Info -Step "Revert-Migration"
        } else {
            Write-ToLog -Message "Migration revert failed for SID: $UserSID. Errors: $($revertResult.Errors -join '; ')" -Level Error -Step "Revert-Migration"
        }

        return $revertResult
    }
}