bin/octa.ps1

#Requires -Version 5.1
<#
    .SYNOPSIS
    Octa CLI entry point. See specs/001-opt-in-debloat-categories/contracts/cli-contract.md.

    .EXAMPLE
    octa --list
    octa --telemetry
    octa --telemetry --appx --clean
    octa --quick --clean --json
    octa --undo latest
#>


Import-Module (Join-Path $PSScriptRoot '..\Octa.psd1') -Force

# -SkipRiskScan: this only needs Id to validate flags against known categories - it ran on
# every single CLI invocation regardless of which flag was passed, paying the full live-scan
# cost (~20s across all 20 categories) just to check a flag name. See Get-OctaCategory.ps1.
$knownCategoryIds = @(Get-OctaCategory -SkipRiskScan | Select-Object -ExpandProperty Id)

$apply = $false
$quick = $false
$noRestorePoint = $false
$yes = $false
$asJson = $false
$quiet = $false
$list = $false
$undoTarget = $null
$categoryIds = @()
$dashboard = $false
$startupManager = $false
$startupDisable = $null
$tasksBrowser = $false
$taskEnable = $null
$taskDisable = $null
$taskRun = $null
$taskStop = $null
$taskDelete = $null
$diskCleanup = $false
$secureDelete = $false
$uninstaller = $false
$removeTarget = $null
$cleanLeftovers = $false
$networkCleanup = $false
$flushDns = $false
$removeWifiProfile = $null
$clearArp = $false
$scheduler = $false
$schedulerCreate = $false
$schedulerCategory = $null
$schedulerFrequency = $null
$softwareUpdater = $false
$history = $false
$diskUsage = $false
$diskUsagePath = $null
$diskUsageTop = $null
$diskHealth = $false
$malwareScan = $false
$malwareScanFull = $false

$i = 0
while ($i -lt $args.Count) {
    $arg = $args[$i]
    # NOTE: PowerShell's switch evaluates every matching case, not just the first (no C-style
    # implicit fallthrough prevention) - each case needs an explicit `break`, otherwise a flag
    # like --list also falls into the generic --<category> case below and errors out.
    switch -Regex ($arg) {
        '^--clean$' { $apply = $true; break }
        '^--quick$' { $quick = $true; break }
        '^--no-restore-point$' { $noRestorePoint = $true; break }
        '^--yes$' { $yes = $true; break }
        '^--json$' { $asJson = $true; break }
        '^(--quiet|-q)$' { $quiet = $true; break }
        '^--verbose$' { break } # activity panel is verbose by nature - no separate flag behavior needed yet
        '^--list$' { $list = $true; break }
        '^--undo$' { $i++; $undoTarget = $args[$i]; break }
        '^--dashboard$' { $dashboard = $true; break }
        '^--startup-manager$' { $startupManager = $true; break }
        '^--disk-cleanup$' { $diskCleanup = $true; break }
        '^--secure-delete$' { $secureDelete = $true; break }
        '^--tasks$' { $tasksBrowser = $true; break }
        '^--uninstaller$' { $uninstaller = $true; break }
        '^--remove$' { $i++; $removeTarget = $args[$i]; break }
        '^--clean-leftovers$' { $cleanLeftovers = $true; break }
        '^--network-cleanup$' { $networkCleanup = $true; break }
        '^--flush-dns$' { $flushDns = $true; break }
        '^--remove-wifi-profile$' { $i++; $removeWifiProfile = $args[$i]; break }
        '^--clear-arp$' { $clearArp = $true; break }
        '^--schedule$' { $scheduler = $true; break }
        '^--create$' { $schedulerCreate = $true; break }
        '^--category$' { $i++; $schedulerCategory = $args[$i]; break }
        '^--frequency$' { $i++; $schedulerFrequency = $args[$i]; break }
        '^--update$' { $softwareUpdater = $true; break }
        '^--history$' { $history = $true; break }
        '^--disk-usage$' { $diskUsage = $true; break }
        '^--path$' { $i++; $diskUsagePath = $args[$i]; break }
        '^--top$' { $i++; $diskUsageTop = $args[$i]; break }
        '^--disk-health$' { $diskHealth = $true; break }
        '^--malware-scan$' { $malwareScan = $true; break }
        '^--full$' { $malwareScanFull = $true; break }
        '^--disable$' {
            $i++
            if ($tasksBrowser) { $taskDisable = $args[$i] } else { $startupDisable = $args[$i] }
            break
        }
        '^--enable$' { $i++; $taskEnable = $args[$i]; break }
        '^--run$' { $i++; $taskRun = $args[$i]; break }
        '^--stop$' { $i++; $taskStop = $args[$i]; break }
        '^--delete$' { $i++; $taskDelete = $args[$i]; break }
        '^--(.+)$' {
            $candidate = $Matches[1]
            if ($candidate -in $knownCategoryIds) {
                $categoryIds += $candidate
            }
            else {
                Write-Error "Unknown flag or category: --$candidate"
                exit 5
            }
            break
        }
    }
    $i++
}

if ($list) {
    Get-OctaCategory | Select-Object Id, DisplayName, RequiresElevation, ContainsIrreversibleActions, HighestRiskLevel |
        Format-Table -AutoSize
    exit 0
}

if ($undoTarget) {
    $result = Undo-OctaRun -RunId $undoTarget
    if ($asJson) { $result | ConvertTo-Json -Depth 6 } else { $result | Format-List }
    if ($result.Status -eq 'NotFound') { exit 4 }
    exit 0
}

if ($dashboard) {
    Show-OctaDashboard | Out-Null
    exit 0
}

if ($startupManager) {
    if ($startupDisable) {
        $result = Invoke-OctaStartupManager -Disable $startupDisable
        if ($asJson) { $result | ConvertTo-Json -Depth 6 } else { $result | Format-List }
    }
    else {
        Invoke-OctaStartupManager | Out-Null
    }
    exit 0
}

if ($tasksBrowser) {
    if ($taskEnable) { $result = Invoke-OctaTaskBrowser -Enable $taskEnable }
    elseif ($taskDisable) { $result = Invoke-OctaTaskBrowser -Disable $taskDisable }
    elseif ($taskRun) { $result = Invoke-OctaTaskBrowser -Run $taskRun }
    elseif ($taskStop) { $result = Invoke-OctaTaskBrowser -Stop $taskStop }
    elseif ($taskDelete) { $result = Invoke-OctaTaskBrowser -Delete $taskDelete -Yes:$yes }
    else { Invoke-OctaTaskBrowser | Out-Null; exit 0 }

    if ($asJson) { $result | ConvertTo-Json -Depth 6 } else { $result | Format-List }
    exit 0
}

if ($diskCleanup) {
    $result = Invoke-OctaDiskCleanup -Apply:$apply -Yes:$yes -SecureDelete:$secureDelete
    if ($asJson) { $result | ConvertTo-Json -Depth 6 } else { $result | Format-List }
    exit 0
}

if ($uninstaller) {
    if ($removeTarget) { $result = Invoke-OctaUninstaller -Remove $removeTarget }
    elseif ($cleanLeftovers) { $result = Invoke-OctaUninstaller -CleanLeftovers -Yes:$yes }
    else { Invoke-OctaUninstaller | Out-Null; exit 0 }

    if ($asJson) { $result | ConvertTo-Json -Depth 6 } else { $result | Format-List }
    exit 0
}

if ($networkCleanup) {
    if ($flushDns) { $result = Invoke-OctaNetworkCleanup -FlushDns }
    elseif ($removeWifiProfile) { $result = Invoke-OctaNetworkCleanup -RemoveWifiProfile $removeWifiProfile }
    elseif ($clearArp) { $result = Invoke-OctaNetworkCleanup -ClearArp }
    else { Invoke-OctaNetworkCleanup | Out-Null; exit 0 }

    if ($asJson) { $result | ConvertTo-Json -Depth 6 } else { $result | Format-List }
    exit 0
}

if ($scheduler) {
    if ($schedulerCreate) { $result = Invoke-OctaScheduler -Create -Category $schedulerCategory -Frequency $schedulerFrequency }
    elseif ($removeTarget) { $result = Invoke-OctaScheduler -Remove $removeTarget }
    else { Invoke-OctaScheduler | Out-Null; exit 0 }

    if ($asJson) { $result | ConvertTo-Json -Depth 6 } else { $result | Format-List }
    exit 0
}

if ($softwareUpdater) {
    $result = Invoke-OctaSoftwareUpdater -Apply:$apply -Yes:$yes
    if ($asJson) { $result | ConvertTo-Json -Depth 6 } else { $result | Format-List }
    exit 0
}

if ($history) {
    $result = Show-OctaHistory
    if ($asJson) { $result | ConvertTo-Json -Depth 6 }
    exit 0
}

if ($diskUsage) {
    $params = @{}
    if ($diskUsagePath) { $params.Path = $diskUsagePath }
    if ($diskUsageTop) { $params.Top = [int]$diskUsageTop }
    $result = Show-OctaDiskUsage @params
    if ($asJson) { $result | ConvertTo-Json -Depth 6 }
    exit 0
}

if ($diskHealth) {
    $result = Show-OctaDiskHealth
    if ($asJson) { $result | ConvertTo-Json -Depth 6 }
    exit 0
}

if ($malwareScan) {
    $result = Invoke-OctaMalwareScan -Full:$malwareScanFull
    if ($asJson) { $result | ConvertTo-Json -Depth 6 } else { $result | Format-List }
    exit 0
}

if (-not $quick -and $categoryIds.Count -eq 0) {
    Invoke-Octa
    exit 0
}

if ($quick) {
    $result = Invoke-OctaQuickClean -Apply:$apply -NoRestorePoint:$noRestorePoint -Yes:$yes -Quiet:$quiet
}
else {
    $result = Invoke-OctaCategory -CategoryId $categoryIds -Apply:$apply -NoRestorePoint:$noRestorePoint -Yes:$yes -Quiet:$quiet
}

if ($asJson) { $result | ConvertTo-Json -Depth 6 } else { $result | Format-List }

switch ($result.Status) {
    'Cancelled' { exit 1 }
    'ElevationRequired' { exit 3 }
    'UnknownCategory' { exit 5 }
    'Error' { exit 5 }
    default { exit 0 }
}