# ASCII-only: Windows PowerShell 5.1 mis-parses UTF-8 without BOM.
# Elevated launcher for Reload-VpnRoutes.ps1
$ErrorActionPreference = "Stop"
$HomeDir = $env:CLAUDE_PROXY_HOME
if (-not $HomeDir) { $HomeDir = Join-Path $env:USERPROFILE ".claude-proxy-control" }
$Merged = Join-Path $HomeDir "merged"
$Logs = Join-Path $HomeDir "logs"
New-Item -ItemType Directory -Force -Path $Logs, $Merged | Out-Null
$Trace = Join-Path $Logs "cpc-trace.log"
$Result = Join-Path $Merged "reload-result.json"

function L([string]$m) {
  $line = "$(Get-Date -Format 'yyyy-MM-ddTHH:mm:ss.fff') [LAUNCHER] INFO  launcher  $m"
  try { Add-Content -Path $Trace -Value $line -Encoding UTF8 } catch {}
  Write-Host $line
}

# Token of the request being served, handed down by the elevate bootstrap. Every result
# this launcher writes must carry it, or the UI cannot tell our verdict apart from a
# leftover file and waits out the whole grace period.
$ReloadToken = $env:CPC_RELOAD_TOKEN
if (-not $ReloadToken) { $ReloadToken = "" }

function Save-Result([bool]$Ok, [string]$Detail) {
  @{
    ok         = $Ok
    detail     = $Detail
    tun        = ""
    token      = $ReloadToken
    time       = (Get-Date).ToString("o")
    launcherId = $PID
  } | ConvertTo-Json | Set-Content -Path $Result -Encoding UTF8
}

try {
  L "begin HOME=$HomeDir pid=$PID"
  $id = [Security.Principal.WindowsIdentity]::GetCurrent()
  $principal = New-Object Security.Principal.WindowsPrincipal($id)
  $isAdmin = $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
  L "isAdmin=$isAdmin ps=$($PSVersionTable.PSVersion)"
  Save-Result $false "launcher-started"

  if (-not $isAdmin) {
    L "NOT ADMIN - cannot reload TUN"
    Save-Result $false "launcher-not-admin"
    exit 2
  }

  $reload = Join-Path $PSScriptRoot "Reload-VpnRoutes.ps1"
  if (-not (Test-Path -LiteralPath $reload)) {
    $reload = Join-Path $HomeDir "Reload-VpnRoutes.ps1"
  }
  L "Reload=$reload exists=$((Test-Path -LiteralPath $reload))"
  if (-not (Test-Path -LiteralPath $reload)) {
    Save-Result $false "reload-script-missing"
    exit 3
  }

  $env:CLAUDE_PROXY_HOME = $HomeDir
  $env:CLAUDE_PROXY_NOPAUSE = "1"
  L "calling Reload-VpnRoutes.ps1 ..."
  & $reload
  $code = 0
  if ($null -ne $LASTEXITCODE) { $code = [int]$LASTEXITCODE }
  # If Reload raised TUN but Write-ReloadResult tripped on a PS quirk, still succeed
  if (($code -ne 0) -and (Test-Path -LiteralPath $Result)) {
    try {
      $rj = Get-Content $Result -Raw -Encoding UTF8 | ConvertFrom-Json
      if ($rj.ok -eq $true) {
        L "Reload reported ok=true in reload-result — treating as success (code was $code)"
        $code = 0
      }
    } catch {}
  }
  L "Reload finished LASTEXITCODE=$code"
  exit $code
} catch {
  $msg = $_.Exception.Message
  L "EXCEPTION: $msg"
  # TUN may already be up — prefer reload-result.ok / status.json over this exception
  if (Test-Path -LiteralPath $Result) {
    try {
      $rj = Get-Content $Result -Raw -Encoding UTF8 | ConvertFrom-Json
      if ($rj.ok -eq $true) {
        L "EXCEPTION after success result — exit 0 anyway"
        exit 0
      }
    } catch {}
  }
  $statusPath = Join-Path $Merged "status.json"
  if (Test-Path -LiteralPath $statusPath) {
    try {
      $st = Get-Content $statusPath -Raw -Encoding UTF8 | ConvertFrom-Json
      if (($st.ok -eq $true) -and ($st.reloaded -eq $true -or $st.appliedRoutes -eq $true) -and $st.tun) {
        L ("EXCEPTION but status shows TUN up tun=" + $st.tun + " — writing ok result, exit 0")
        Save-Result $true ("TUN up (recovered after: " + $msg + ")")
        # Preserve tun in result
        try {
          @{
            ok         = $true
            detail     = ("TUN up recovered: " + $msg)
            tun        = [string]$st.tun
            singBoxPid = $(if ($st.singBoxPid) { [int]$st.singBoxPid } else { 0 })
            token      = ""
            time       = (Get-Date).ToString("o")
          } | ConvertTo-Json | Set-Content -Path $Result -Encoding UTF8
        } catch {}
        exit 0
      }
    } catch {}
  }
  try { Save-Result $false ("launcher-exception: " + $msg) } catch {}
  exit 1
}
