# Beendet alle laufenden Prozesse dieses Projekts (Electron, Node/Vite, und
# einen verwaisten lokalen Input-Helper-Kindprozess), bevor eine neue Instanz
# startet.
#
# Warum das noetig ist: Ein normales Schliessen der App (X-Button) raeumt
# sauber auf (main.ts: app.on("will-quit") beendet den gespawnten
# input-helper.ps1-Kindprozess). Wird die App aber gewaltsam beendet - z.B.
# ueber Task-Manager "Task beenden" oder ein Skript, das Stop-Process -Force
# auf den Electron-Prozess anwendet - greift dieser Cleanup-Handler NICHT,
# und der Kindprozess (PowerShell mit dem Input-Helper) bleibt als Waise
# aktiv, obwohl das Hauptfenster laengst weg ist. Dieses Skript faengt genau
# das ab: es wird vor JEDEM Start (npm run dev und npm run dev:admin, ueber
# den "predev"-Hook) ausgefuehrt und raeumt vorherige Instanzen kompromisslos
# weg, egal wie sie beendet wurden.

$ErrorActionPreference = "Stop"
$project = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")).Path
$electronPath = Join-Path $project "node_modules\electron\dist\electron.exe"
$devControlPort = 17317

$killed = 0
$candidatePids = @{}

try {
  $health = Invoke-RestMethod -Method Get -Uri "http://127.0.0.1:$devControlPort/health" -TimeoutSec 2 -ErrorAction Stop
  if ($health.appBuild -and $health.appBuild.cwd -eq $project) {
    Write-Host "Dev-Control-Port $devControlPort gehoert zu diesem Projekt (PID $($health.appBuild.pid), Signatur $($health.appBuild.signature)). Versuche Self-Shutdown..."
    try {
      Invoke-RestMethod -Method Get -Uri "http://127.0.0.1:$devControlPort/dev/shutdown?reason=restart" -TimeoutSec 2 -ErrorAction Stop | Out-Null
      Start-Sleep -Milliseconds 900
    } catch {
      Write-Host "Self-Shutdown nicht verfuegbar oder fehlgeschlagen: $($_.Exception.Message)" -ForegroundColor Yellow
    }
  }
} catch {
  # No dev-control server or an older/stuck process; continue with process scan.
}

Get-CimInstance Win32_Process |
  Where-Object {
    ($_.Name -eq "electron.exe" -and $_.ExecutablePath -eq $electronPath) -or
    ($_.Name -eq "node.exe" -and $_.CommandLine -like "*$project*") -or
    ($_.Name -eq "powershell.exe" -and $_.CommandLine -like "*input-helper.ps1*")
  } |
  ForEach-Object {
    $candidatePids[[int]$_.ProcessId] = $_.Name
  }

try {
  Get-NetTCPConnection -LocalPort $devControlPort -State Listen -ErrorAction Stop |
    ForEach-Object {
      if ($_.OwningProcess -gt 0) {
        $owner = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue
        $candidatePids[[int]$_.OwningProcess] = if ($owner) { "$($owner.ProcessName) port $devControlPort" } else { "port $devControlPort owner" }
      }
    }
} catch {
  # Get-NetTCPConnection can be unavailable on some machines; process matching
  # above still handles the normal non-elevated path.
}

$failed = 0
foreach ($entry in $candidatePids.GetEnumerator()) {
  Write-Host "Beende alte Instanz: $($entry.Value) (PID $($entry.Key))"
  try {
    Stop-Process -Id $entry.Key -Force -ErrorAction Stop
    $killed++
  } catch {
    Write-Host "WARNUNG: Konnte PID $($entry.Key) nicht beenden: $($_.Exception.Message)" -ForegroundColor Yellow
    $failed++
  }
}

if ($killed -gt 0) {
  # Windows braucht einen Moment, um Ports/Handles wirklich freizugeben.
  Start-Sleep -Milliseconds 500
  Write-Host "$killed alte Prozess(e) beendet."
}

if ($failed -gt 0) {
  Write-Host "$failed alte Prozess(e) konnten nicht beendet werden. Wenn das ein Admin-Prozess ist, starte npm run dev:admin und bestaetige UAC oder schliesse die alte App manuell." -ForegroundColor Yellow
  throw "$failed alte Prozess(e) konnten nicht beendet werden."
}

if ($killed -eq 0 -and $failed -eq 0) {
  Write-Host "Keine alten Instanzen gefunden."
} else {
  Start-Sleep -Milliseconds 300
}
