param(
  [string]$ServerId,
  [string]$Token,
  [string]$ServerUrl,
  [string]$InstallDir,
  [switch]$Uninstall
)

$ErrorActionPreference = "Stop"
$logDir = Join-Path $env:ProgramData "vantage"
New-Item -ItemType Directory -Force -Path $logDir | Out-Null
$log = Join-Path $logDir "install.log"

function Write-Log($msg) {
  $line = "{0} {1}" -f (Get-Date -Format "s"), $msg
  Add-Content -Path $log -Value $line
}

# Fail native-exe (nssm) calls loudly: check $LASTEXITCODE after each call
function Invoke-Native {
  param([string]$File, [string[]]$Arguments)
  Write-Log ("RUN: {0} {1}" -f $File, ($Arguments -join " "))
  $out = & $File @Arguments 2>&1
  if ($out) { Write-Log ("OUT: {0}" -f ($out -join "`n")) }
  if ($LASTEXITCODE -ne 0) {
    throw ("{0} exited {1}" -f $File, $LASTEXITCODE)
  }
}

function Invoke-NativeSoft {
  param([string]$File, [string[]]$Arguments)
  Write-Log ("RUN(soft): {0} {1}" -f $File, ($Arguments -join " "))
  # Native stderr merged via 2>&1 becomes terminating errors under
  # ErrorActionPreference=Stop; force Continue in this scope so a benign nssm
  # message (e.g. "service has not been started") never aborts setup.
  $ErrorActionPreference = "Continue"
  $out = & $File @Arguments 2>&1
  if ($out) { Write-Log ("OUT: {0}" -f ($out -join "`n")) }
  Write-Log ("EXIT: {0}" -f $LASTEXITCODE)
}

if ($Uninstall) {
  try {
    Write-Log "=== teardown start ==="
    if (-not $InstallDir) { $InstallDir = $PSScriptRoot }
    $nssm = Join-Path $InstallDir "nssm.exe"
    if (Test-Path $nssm) {
      Invoke-NativeSoft -File $nssm -Arguments @("stop", "VantageAgent")
      Invoke-NativeSoft -File $nssm -Arguments @("remove", "VantageAgent", "confirm")
    } else {
      Write-Log "nssm.exe not found at $nssm - using sc.exe fallback"
      Invoke-NativeSoft -File "sc.exe" -Arguments @("stop", "VantageAgent")
      Invoke-NativeSoft -File "sc.exe" -Arguments @("delete", "VantageAgent")
    }
    Write-Log "=== teardown ok ==="
    exit 0
  }
  catch {
    Write-Log ("TEARDOWN ERROR: {0}" -f $_.Exception.Message)
    # Never block uninstall
    exit 0
  }
}

try {
  Write-Log "=== setup start ==="
  Write-Log ("ServerId={0} ServerUrl={1} InstallDir={2}" -f $ServerId, $ServerUrl, $InstallDir)

  $cfgDir = Join-Path $env:ProgramData "vantage"
  New-Item -ItemType Directory -Force -Path $cfgDir | Out-Null
  $cfgPath = Join-Path $cfgDir "config.yaml"

  # Preserve existing config on upgrade. A MajorUpgrade re-runs this script with
  # no SERVERID/TOKEN, so blindly rewriting would wipe the agent_token the agent
  # persisted after Register(). Only (re)write when a ServerId is supplied
  # (fresh install / explicit re-register).
  if ((Test-Path $cfgPath) -and (-not $ServerId)) {
    Write-Log "config.yaml exists and no ServerId supplied - preserving existing config (upgrade)"
  }
  else {
    $cfg = @"
server_url: "$ServerUrl"
server_id: "$ServerId"
pre_reg_token: "$Token"
agent_token: ""
poll_interval: 30s
tls: true
"@
    Set-Content -Path $cfgPath -Value $cfg -Encoding utf8
    Write-Log "wrote $cfgPath"

    # Lock down ACL: SYSTEM + Administrators only
    Invoke-Native -File "icacls" -Arguments @($cfgPath, "/inheritance:r", "/grant:r", "SYSTEM:F", "Administrators:F")
  }

  if (-not $InstallDir) { $InstallDir = $PSScriptRoot }
  $nssm = Join-Path $InstallDir "nssm.exe"
  $exe  = Join-Path $InstallDir "vantage-agent.exe"

  if (-not (Test-Path $nssm)) { throw "nssm.exe not found at $nssm" }
  if (-not (Test-Path $exe))  { throw "vantage-agent.exe not found at $exe" }

  # Install only if the service isn't already registered (an upgrade may leave
  # it in place). "nssm install" on an existing service errors otherwise.
  $exists = Get-Service -Name "VantageAgent" -ErrorAction SilentlyContinue
  if (-not $exists) {
    Invoke-Native -File $nssm -Arguments @("install", "VantageAgent", $exe)
  } else {
    Write-Log "VantageAgent service already exists - updating binary path"
    Invoke-Native -File $nssm -Arguments @("set", "VantageAgent", "Application", $exe)
  }
  Invoke-Native -File $nssm -Arguments @("set", "VantageAgent", "Start", "SERVICE_AUTO_START")

  # Redirect service stdout/stderr to log files (nssm discards them otherwise)
  # with online rotation at ~1MB.
  $outLog = Join-Path $logDir "agent-stdout.log"
  $errLog = Join-Path $logDir "agent-stderr.log"
  Invoke-Native -File $nssm -Arguments @("set", "VantageAgent", "AppStdout", $outLog)
  Invoke-Native -File $nssm -Arguments @("set", "VantageAgent", "AppStderr", $errLog)
  Invoke-Native -File $nssm -Arguments @("set", "VantageAgent", "AppStdoutCreationDisposition", "4")
  Invoke-Native -File $nssm -Arguments @("set", "VantageAgent", "AppStderrCreationDisposition", "4")
  Invoke-Native -File $nssm -Arguments @("set", "VantageAgent", "AppRotateFiles", "1")
  Invoke-Native -File $nssm -Arguments @("set", "VantageAgent", "AppRotateOnline", "1")
  Invoke-Native -File $nssm -Arguments @("set", "VantageAgent", "AppRotateBytes", "1048576")

  # Service is freshly (re)installed and stopped here (teardown removed the old
  # one on upgrade), so start it. "restart" would try to stop a not-running
  # service and emit a stderr error.
  Invoke-NativeSoft -File $nssm -Arguments @("start", "VantageAgent")

  Write-Log "=== setup ok ==="
  exit 0
}
catch {
  Write-Log ("ERROR: {0}" -f $_.Exception.Message)
  Write-Log ($_.ScriptStackTrace)
  exit 1
}
