categories/WindowsFeatures.ps1

# Windows Features category: remove Microsoft Edge (irreversible), enable Windows Sandbox,
# enable Windows Subsystem for Linux. research.md -> windows-features category table.
#
# ponytail: Sandbox requires Pro/Enterprise/Education (not Home) - detected via EditionID and
# reported as "nothing to do" on unsupported editions rather than failing, same pattern gpu/
# oem-suites already use for hardware/vendor detection.

function Get-OctaWindowsFeaturesCategory {
    [CmdletBinding()]
    param()
    return [pscustomobject]@{
        Id                          = 'windows-features'
        DisplayName                 = 'Windows Features'
        Description                 = 'Remove Edge, enable Sandbox/WSL'
        RequiresElevation           = $true
        ContainsIrreversibleActions = $true
        GetActionsFunction          = 'Get-OctaWindowsFeaturesActions'
        ApplyActionFunction         = 'Set-OctaWindowsFeaturesAction'
    }
}

function Get-OctaWindowsFeaturesActions {
    [CmdletBinding()]
    param()
    $actions = @()

    $edgeInstalled = Get-ChildItem -Path 'C:\Program Files (x86)\Microsoft\Edge\Application' -Directory -ErrorAction SilentlyContinue |
        Where-Object { $_.Name -match '^\d+\.' } | Select-Object -First 1
    if ($edgeInstalled) {
        $actions += New-OctaAction -TargetType Package -TargetIdentifier 'MicrosoftEdge' `
            -CurrentValue 'installed' -PlannedValue 'removed' -Reversible $false `
            -IrreversibleReason 'Windows provides no supported "reinstall Edge" path outside a full Windows feature update or a manually-downloaded enterprise MSI.' `
            -RiskLevel Risky
    }

    $editionId = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name 'EditionID' -ErrorAction SilentlyContinue).EditionID
    $sandboxSupported = $editionId -and $editionId -notmatch 'Core|Home'
    if ($sandboxSupported) {
        $sandboxFeature = Get-WindowsOptionalFeature -Online -FeatureName 'Containers-DisposableClientVM' -ErrorAction SilentlyContinue
        if ($sandboxFeature -and $sandboxFeature.State -ne 'Enabled') {
            $actions += New-OctaAction -TargetType Package -TargetIdentifier 'Containers-DisposableClientVM' `
                -CurrentValue $sandboxFeature.State -PlannedValue 'Enabled' -Reversible $true -RiskLevel Safe
        }
    }

    $wslFeature = Get-WindowsOptionalFeature -Online -FeatureName 'Microsoft-Windows-Subsystem-Linux' -ErrorAction SilentlyContinue
    if ($wslFeature -and $wslFeature.State -ne 'Enabled') {
        $actions += New-OctaAction -TargetType Package -TargetIdentifier 'Microsoft-Windows-Subsystem-Linux' `
            -CurrentValue $wslFeature.State -PlannedValue 'Enabled' -Reversible $true -RiskLevel Safe
    }

    return $actions
}

function Set-OctaWindowsFeaturesAction {
    [CmdletBinding()]
    param([Parameter(Mandatory)]$Action)

    switch ($Action.TargetIdentifier) {
        'MicrosoftEdge' {
            $edgeDir = Get-ChildItem -Path 'C:\Program Files (x86)\Microsoft\Edge\Application' -Directory -ErrorAction SilentlyContinue |
                Where-Object { $_.Name -match '^\d+\.' } | Select-Object -First 1
            if ($edgeDir) {
                $setupExe = Join-Path $edgeDir.FullName 'Installer\setup.exe'
                & $setupExe --uninstall --system-level --verbose-logging --force-uninstall | Out-Null
            }
        }
        default {
            Enable-WindowsOptionalFeature -Online -FeatureName $Action.TargetIdentifier -All -NoRestart | Out-Null
        }
    }
}