param(
    [string]$CertificateSubject = "CN=OlivePrivate",
    [switch]$RemoveCertificate,
    [switch]$KeepCertificate,
    [switch]$KeepUserData,
    [switch]$Yes
)

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

function Confirm-Continue {
    $removeCertificateNow = $RemoveCertificate -or -not $KeepCertificate
    $removeUserDataNow = -not $KeepUserData

    if ($Yes) {
        return
    }

    Write-Host "This script will uninstall Olive for the current Windows user." -ForegroundColor Yellow
    if ($removeCertificateNow) {
        Write-Host "It will also remove certificates with subject: $CertificateSubject"
    } else {
        Write-Host "It will keep the trusted certificate because -KeepCertificate was used."
    }
    if ($removeUserDataNow) {
        Write-Host "It will also remove Olive user data."
    } else {
        Write-Host "It will keep Olive user data because -KeepUserData was used."
    }
    $answer = Read-Host "Continue? Type YES"
    if ($answer -ne "YES") {
        throw "Cancelled by user."
    }
}

function Remove-DirectoryIfExists {
    param([string]$Path)

    if ([string]::IsNullOrWhiteSpace($Path) -or -not (Test-Path -LiteralPath $Path)) {
        return
    }

    Write-Host "==> Removing directory $Path" -ForegroundColor Cyan
    Remove-Item -LiteralPath $Path -Recurse -Force
}

function Test-IsAdministrator {
    $identity = [Security.Principal.WindowsIdentity]::GetCurrent()
    $principal = [Security.Principal.WindowsPrincipal]::new($identity)
    return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}

function Remove-CertificatesBySubject {
    param(
        [string]$StorePath,
        [string]$Subject
    )

    if (-not (Test-Path -LiteralPath $StorePath)) {
        return
    }

    Get-ChildItem $StorePath | Where-Object { $_.Subject -eq $Subject } | ForEach-Object {
        Write-Host "==> Removing certificate $($_.Thumbprint) from $StorePath" -ForegroundColor Cyan
        Remove-Item -LiteralPath $_.PSPath -Force
    }
}

if (($RemoveCertificate -or -not $KeepCertificate) -and -not (Test-IsAdministrator)) {
    throw "Administrator rights are required to remove the Olive signing certificate from Cert:\LocalMachine\Root. Run Uninstall-Olive.cmd, or use -KeepCertificate."
}

Confirm-Continue

$packages = @(Get-AppxPackage -Name Olive)
$packageFamilyNames = @($packages | ForEach-Object { $_.PackageFamilyName } | Sort-Object -Unique)
if ($packages.Count -eq 0) {
    Write-Host "Olive is not installed for the current user." -ForegroundColor Yellow
} else {
    foreach ($package in $packages) {
        Write-Host "==> Removing package $($package.PackageFullName)" -ForegroundColor Cyan
        Remove-AppxPackage -Package $package.PackageFullName
    }
}

if (-not $KeepUserData) {
    $localAppData = [Environment]::GetFolderPath([Environment+SpecialFolder]::LocalApplicationData)
    $userDataPaths = @(
        (Join-Path $localAppData "Microsoft\PowerToys\CommandPalette\Extensions\Olive"),
        (Join-Path $localAppData "Microsoft\PowerToys\CommandPalette\Settings\Olive"),
        (Join-Path $localAppData "Microsoft\PowerToys\CommandPalette\Olive")
    )

    foreach ($packageFamilyName in $packageFamilyNames) {
        $userDataPaths += Join-Path $localAppData "Packages\$packageFamilyName"
    }

    $packagesRoot = Join-Path $localAppData "Packages"
    if (Test-Path -LiteralPath $packagesRoot) {
        $userDataPaths += Get-ChildItem -LiteralPath $packagesRoot -Directory -Filter "Olive_*" |
            ForEach-Object { $_.FullName }
    }

    foreach ($path in ($userDataPaths | Sort-Object -Unique)) {
        Remove-DirectoryIfExists -Path $path
    }
}

if ($RemoveCertificate -or -not $KeepCertificate) {
    Remove-CertificatesBySubject -StorePath "Cert:\LocalMachine\Root" -Subject $CertificateSubject
}

Write-Host ""
Write-Host "Olive uninstall completed." -ForegroundColor Green
