param(
    [string]$ServiceName = "SyncVisionServer",

    [string]$InstallDir = (Join-Path $env:ProgramFiles "SyncVision\Server"),

    [string]$DataDir = (Join-Path $env:ProgramData "SyncVision\Server"),

    [switch]$RemoveInstallDir,

    [switch]$RemoveDataDir,

    [switch]$RemoveFirewallRules,

    [switch]$WhatIf,

    [switch]$TestMode
)

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

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

function Write-SyncVisionPlan {
    param(
        [Parameter(Mandatory = $true)]
        [string]$Message
    )

    Write-Output "[WhatIf] $Message"
}

function Get-SyncVisionFirewallRuleDisplayNamePattern {
    param(
        [Parameter(Mandatory = $true)]
        [string]$ServiceName
    )

    return "SyncVision * ($ServiceName) *"
}

function Remove-SyncVisionFirewallRules {
    param(
        [Parameter(Mandatory = $true)]
        [string]$ServiceName
    )

    if (-not (Get-Command Get-NetFirewallRule -ErrorAction SilentlyContinue)) {
        throw "Get-NetFirewallRule is unavailable. Install or enable the Windows NetSecurity module, or remove SyncVision firewall rules manually."
    }
    if (-not (Get-Command Remove-NetFirewallRule -ErrorAction SilentlyContinue)) {
        throw "Remove-NetFirewallRule is unavailable. Install or enable the Windows NetSecurity module, or remove SyncVision firewall rules manually."
    }

    $pattern = Get-SyncVisionFirewallRuleDisplayNamePattern -ServiceName $ServiceName
    $rules = @(Get-NetFirewallRule -DisplayName $pattern -ErrorAction SilentlyContinue)
    if ($rules.Count -eq 0) {
        Write-Host "No SyncVision Windows Firewall rules matched: $pattern"
        return
    }

    $rules | Remove-NetFirewallRule
    Write-Host "Removed SyncVision Windows Firewall rules matching: $pattern"
}

if ($TestMode) {
    return
}

if (-not $WhatIf -and -not (Test-SyncVisionAdministrator)) {
    throw "Uninstalling the SyncVision Windows service requires an elevated PowerShell session. Re-run as Administrator, or use -WhatIf for a dry run."
}

if ($WhatIf) {
    Write-SyncVisionPlan "Would stop service '$ServiceName' if it exists and is running."
    Write-SyncVisionPlan "Would delete service '$ServiceName' if it exists."
    if ($RemoveFirewallRules) {
        Write-SyncVisionPlan "Would remove Windows Firewall rules matching: $(Get-SyncVisionFirewallRuleDisplayNamePattern -ServiceName $ServiceName)"
    }
    if ($RemoveInstallDir) {
        Write-SyncVisionPlan "Would remove install directory: $InstallDir"
    }
    if ($RemoveDataDir) {
        Write-SyncVisionPlan "Would remove data directory: $DataDir"
    }
    return
}

$service = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if ($service) {
    if ($service.Status -ne "Stopped") {
        Stop-Service -Name $ServiceName -Force -ErrorAction Stop
        $service.WaitForStatus("Stopped", [TimeSpan]::FromSeconds(30))
    }

    & sc.exe delete $ServiceName
    if ($LASTEXITCODE -ne 0) {
        exit $LASTEXITCODE
    }
}
else {
    Write-Host "Service '$ServiceName' was not found."
}

if ($RemoveFirewallRules) {
    Remove-SyncVisionFirewallRules -ServiceName $ServiceName
}

if ($RemoveInstallDir -and (Test-Path -LiteralPath $InstallDir)) {
    Remove-Item -LiteralPath $InstallDir -Recurse -Force
}

if ($RemoveDataDir -and (Test-Path -LiteralPath $DataDir)) {
    Remove-Item -LiteralPath $DataDir -Recurse -Force
}

Write-Host "Uninstall command completed for service '$ServiceName'."
