public/Restore-PSProfileSnapshot.ps1

<#
    .SYNOPSIS
        Restores the current profile from a specific snapshot.
    .DESCRIPTION
        Restores the user's PowerShell profile from a previously saved snapshot.
        The user can select a snapshot by name or by GUID. The current profile
        is backed up before restoration in case the restore needs to be undone.
    .PARAMETER Name
        The name of the snapshot to restore from. Use Get-PSProfileSnapshot to
        list available snapshots. If not specified, the most recent snapshot
        is used by default. Can be piped from Get-PSProfileSnapshot.
    .PARAMETER GUID
        The GUID of the snapshot to restore. Used as an alternative to Name
        for precise snapshot identification. Format: 12345678-1234-1234-1234-123456789abc
        Can be piped from Get-PSProfileSnapshot.
    .INPUTS
        None
    .OUTPUTS
        None
    .EXAMPLE
        Restore-PSProfileSnapshot

        Restores the profile from the most recent snapshot.
    .EXAMPLE
        Restore-PSProfileSnapshot -Name "before-major-change"

        Restores the profile from a snapshot with a custom name.
    .EXAMPLE
        Get-PSProfileSnapshot | Where-Object Name -EQ "stable-config" | Restore-PSProfileSnapshot

        Restores profile by piping from Get-PSProfileSnapshot.
    .NOTES
        A safety backup of the current profile is created before restoration.
        If restoration fails, the profile remains unchanged.
#>


function Restore-PSProfileSnapshot {
    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')]
    param(
        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
        [Alias('SnapshotName')]
        [string]$Name,

        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)]
        [Alias('SnapshotGUID')]
        [guid]$GUID
    )

    try {
        $profilesPath = Split-Path -Path $profile -Parent
        
        # Find the snapshot to restore
        $snapshotBackupFile = $null

        if ($GUID) {
            # Search by GUID
            $snapshotBackupFile = Get-ChildItem -Path $profilesPath -Filter "*_$($GUID).backup" -ErrorAction Stop | 
                Select-Object -First 1
            
            if (-not $snapshotBackupFile) {
                Write-Error "❌ No snapshot found with GUID: $GUID"
                return
            }
        }
        elseif ($Name) {
            # Search by name (custom name from metadata or timestamp)
            $backupFiles = Get-ChildItem -Path $profilesPath -Filter "*.backup" -ErrorAction Stop
            
            foreach ($backupFile in $backupFiles) {
                $guid = $backupFile.BaseName -replace '^.*_([a-f0-9\-]+)$', '$1'
                $metadataFileName = "$($profile)_$($guid).metadata"
                
                # Check metadata first for custom name
                if (Test-Path -Path $metadataFileName -ErrorAction SilentlyContinue) {
                    $metadata = Get-Content -Path $metadataFileName -Raw | ConvertFrom-Json -ErrorAction SilentlyContinue
                    if ($metadata.Name -eq $Name) {
                        $snapshotBackupFile = $backupFile
                        break
                    }
                }
                
                # Also check if name matches the timestamp format of CreatedTime
                $timestampName = $backupFile.CreationTime.ToString("yyyy-MM-dd HH:mm:ss")
                if ($timestampName -eq $Name) {
                    $snapshotBackupFile = $backupFile
                    break
                }
            }

            if (-not $snapshotBackupFile) {
                Write-Error "❌ No snapshot found with name: $Name"
                return
            }
        }
        else {
            # Use most recent snapshot
            $snapshotBackupFile = Get-ChildItem -Path $profilesPath -Filter "*.backup" -ErrorAction Stop | 
                Sort-Object -Property CreationTime | 
                Select-Object -Last 1
            
            if (-not $snapshotBackupFile) {
                Write-Error "❌ No snapshots available to restore from."
                return
            }
        }

        # Create a pre-restoration backup as safety measure
        $safetyBackupGUID = [guid]::NewGuid()
        $safetyBackupFile = "$($profile)_$($safetyBackupGUID).backup.pre-restore"

        $actionTarget = "profile from snapshot: $($snapshotBackupFile.Name)"
        if ($PSCmdlet.ShouldProcess($actionTarget, 'Restore')) {
            try {
                # Create safety backup
                Copy-Item -Path $profile -Destination $safetyBackupFile -Force -ErrorAction Stop
                
                # Restore from snapshot
                Copy-Item -Path $snapshotBackupFile.FullName -Destination $profile -Force -ErrorAction Stop
                
                Write-Host "✅ Profile restored successfully from snapshot: $($snapshotBackupFile.Name)" -ForegroundColor Green
                Write-Host "ℹ️ A safety backup was created at: $safetyBackupFile" -ForegroundColor Cyan
            }
            catch {
                Write-Error "❌ Could not restore profile from snapshot."
                # Clean up safety backup if restoration failed
                if (Test-Path -Path $safetyBackupFile -ErrorAction SilentlyContinue) {
                    Remove-Item -Path $safetyBackupFile -Force -ErrorAction SilentlyContinue
                }
                throw $_.Exception.Message
            }
        }
    }
    catch {
        Write-Error "❌ An error occurred during snapshot restoration."
        throw $_.Exception.Message
    }
}