#Requires -Version 7.4

function Remove-vSEALRegistryKey {
    <#
    .SYNOPSIS
        Removes a registry key or value.

    .DESCRIPTION
        Removes a registry key or specific value with support for recursive deletion,
        WOW6432Node redirection, and user-specific registry access via SID.
        Uses Convert-vSEALRegistryPath internally for path normalization.

    .PARAMETER LiteralPath
        The literal registry key path (e.g., HKLM:\SOFTWARE\Microsoft).
        Wildcards are not processed. This is the default parameter set.

    .PARAMETER Path
        The registry key path. Supports wildcards.

    .PARAMETER Name
        The name of the specific registry value to remove. If not specified,
        the entire key is removed. Use "(Default)" to remove the default value.

    .PARAMETER Recurse
        Recursively remove the key and all its subkeys. Required when key has subkeys.

    .PARAMETER Wow6432Node
        Access the 32-bit registry view on 64-bit systems.

    .PARAMETER SID
        User SID for accessing user-specific registry (converts HKCU to HKU\SID).

    .OUTPUTS
        [void]

    .EXAMPLE
        Remove-vSEALRegistryKey -LiteralPath 'HKLM:\SOFTWARE\Test' -Name 'Setting'
        Removes the specific registry value 'Setting'.

    .EXAMPLE
        Remove-vSEALRegistryKey -LiteralPath 'HKLM:\SOFTWARE\Test' -Recurse
        Removes the entire registry key and all its subkeys.

    .EXAMPLE
        Remove-vSEALRegistryKey -LiteralPath 'HKCU:\Software\Test' -SID 'S-1-5-21-123456789'
        Removes a key from another user's registry hive.

    .EXAMPLE
        Remove-vSEALRegistryKey -LiteralPath 'HKLM:\SOFTWARE\Test' -Name '(Default)'
        Removes the default value from the registry key.
    #>
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High', DefaultParameterSetName = 'LiteralPath')]
    [OutputType([void])]
    param(
        [Parameter(Mandatory, Position = 0, ParameterSetName = 'LiteralPath')]
        [ValidateNotNullOrEmpty()]
        [Alias('Key')]
        [string]$LiteralPath,

        [Parameter(Mandatory, Position = 0, ParameterSetName = 'Path')]
        [ValidateNotNullOrEmpty()]
        [SupportsWildcards()]
        [string]$Path,

        [Parameter(Position = 1)]
        [string]$Name,

        [Parameter()]
        [switch]$Recurse,

        [Parameter()]
        [switch]$Wow6432Node,

        [Parameter()]
        [string]$SID
    )

    # Determine which path to use
    $registryPath = if ($PSCmdlet.ParameterSetName -eq 'Path') { $Path } else { $LiteralPath }

    # Convert the registry path using the helper function
    $convertParams = @{
        Key = $registryPath
    }
    if ($Wow6432Node) {
        $convertParams['Wow6432Node'] = $true
    }
    if ($SID) {
        $convertParams['SID'] = $SID
    }

    try {
        $convertedPath = Convert-vSEALRegistryPath @convertParams
    }
    catch {
        Write-vSEALLog -Message "Failed to convert registry path '$registryPath': $($_.Exception.Message)" -Level 'ERROR'
        throw
    }

    # Handle wildcard paths
    if ($PSCmdlet.ParameterSetName -eq 'Path' -and [System.Management.Automation.WildcardPattern]::ContainsWildcardCharacters($Path)) {
        $matchingPaths = Get-Item -Path $convertedPath -ErrorAction SilentlyContinue
        if (-not $matchingPaths) {
            Write-vSEALLog -Message "No registry keys matched pattern: $convertedPath" -Level 'VERBOSE'
            return
        }

        foreach ($matchingPath in $matchingPaths) {
            Remove-vSEALRegistryKeyInternal -ConvertedPath $matchingPath.PSPath -Name $Name -Recurse:$Recurse -CallerPSCmdlet $PSCmdlet
        }
        return
    }

    Remove-vSEALRegistryKeyInternal -ConvertedPath $convertedPath -Name $Name -Recurse:$Recurse -CallerPSCmdlet $PSCmdlet
}

function Remove-vSEALRegistryKeyInternal {
    param(
        [string]$ConvertedPath,
        [string]$Name,
        [switch]$Recurse,
        [System.Management.Automation.PSCmdlet]$CallerPSCmdlet
    )

    # Check if the key exists
    if (-not (Test-Path -LiteralPath $ConvertedPath)) {
        Write-vSEALLog -Message "Registry key does not exist: $ConvertedPath" -Level 'VERBOSE'
        return
    }

    if ($Name) {
        # Remove specific value
        Write-vSEALLog -Message "Removing registry value: $ConvertedPath\$Name" -Level 'VERBOSE'

        if ($CallerPSCmdlet.ShouldProcess("$ConvertedPath\$Name", 'Remove registry value')) {
            try {
                # Special handling for (Default) value - use .NET Registry API
                if ($Name -eq '(Default)' -or $Name -eq '') {
                    $regKey = Get-Item -LiteralPath $ConvertedPath
                    if ($null -ne $regKey) {
                        # Get the underlying registry key and delete the default value
                        $hive = $null
                        $subKeyPath = $null

                        # Parse the converted path to get hive and subkey
                        if ($ConvertedPath -match 'Registry::HKEY_LOCAL_MACHINE\\(.+)$') {
                            $hive = [Microsoft.Win32.Registry]::LocalMachine
                            $subKeyPath = $Matches[1]
                        }
                        elseif ($ConvertedPath -match 'Registry::HKEY_CURRENT_USER\\(.+)$') {
                            $hive = [Microsoft.Win32.Registry]::CurrentUser
                            $subKeyPath = $Matches[1]
                        }
                        elseif ($ConvertedPath -match 'Registry::HKEY_USERS\\(.+)$') {
                            $hive = [Microsoft.Win32.Registry]::Users
                            $subKeyPath = $Matches[1]
                        }
                        elseif ($ConvertedPath -match 'Registry::HKEY_CLASSES_ROOT\\(.+)$') {
                            $hive = [Microsoft.Win32.Registry]::ClassesRoot
                            $subKeyPath = $Matches[1]
                        }
                        elseif ($ConvertedPath -match 'Registry::HKEY_CURRENT_CONFIG\\(.+)$') {
                            $hive = [Microsoft.Win32.Registry]::CurrentConfig
                            $subKeyPath = $Matches[1]
                        }

                        if ($hive -and $subKeyPath) {
                            $openedKey = $hive.OpenSubKey($subKeyPath, $true)
                            if ($openedKey) {
                                try {
                                    $openedKey.DeleteValue('', $false)
                                    Write-vSEALLog -Message "Removed default registry value: $ConvertedPath" -Level 'VERBOSE'
                                }
                                finally {
                                    $openedKey.Close()
                                }
                            }
                        }
                    }
                }
                else {
                    Remove-ItemProperty -LiteralPath $ConvertedPath -Name $Name -ErrorAction Stop
                    Write-vSEALLog -Message "Removed registry value: $ConvertedPath\$Name" -Level 'VERBOSE'
                }
            }
            catch [System.Management.Automation.ItemNotFoundException] {
                Write-vSEALLog -Message "Registry value not found: $ConvertedPath\$Name" -Level 'VERBOSE'
            }
            catch [System.Management.Automation.PSArgumentException] {
                Write-vSEALLog -Message "Registry value not found: $ConvertedPath\$Name" -Level 'VERBOSE'
            }
            catch {
                Write-vSEALLog -Message "Failed to remove registry value '$ConvertedPath\$Name': $($_.Exception.Message)" -Level 'ERROR'
                throw
            }
        }
    }
    else {
        # Remove entire key
        Write-vSEALLog -Message "Removing registry key: $ConvertedPath" -Level 'VERBOSE'

        if ($CallerPSCmdlet.ShouldProcess($ConvertedPath, 'Remove registry key')) {
            try {
                $removeParams = @{
                    LiteralPath = $ConvertedPath
                    ErrorAction = 'Stop'
                }
                if ($Recurse) {
                    $removeParams['Recurse'] = $true
                }

                Remove-Item @removeParams
                Write-vSEALLog -Message "Removed registry key: $ConvertedPath" -Level 'VERBOSE'
            }
            catch {
                Write-vSEALLog -Message "Failed to remove registry key '$ConvertedPath': $($_.Exception.Message)" -Level 'ERROR'
                throw
            }
        }
    }
}
