param(
  [Parameter(Mandatory = $true)][int]$ParentPid,
  [Parameter(Mandatory = $true)][string]$SourceDir,
  [Parameter(Mandatory = $true)][string]$TargetDir,
  [Parameter(Mandatory = $true)][string]$LogPath,
  [switch]$DryRun
)

$ErrorActionPreference = 'Stop'

function Write-UpdateLog([string]$Message) {
  $stamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
  Add-Content -LiteralPath $LogPath -Value "[$stamp] $Message" -Encoding UTF8
}

$sourceRoot = [System.IO.Path]::GetFullPath($SourceDir)
$targetRoot = [System.IO.Path]::GetFullPath($TargetDir)
$sourceExe = Join-Path $sourceRoot 'xmath-print-bridge.exe'
$targetExe = Join-Path $targetRoot 'xmath-print-bridge.exe'
$tempExe = Join-Path $targetRoot 'xmath-print-bridge.exe.update.tmp'
$supportFiles = @(
  'config.example.json',
  'README.md',
  'run_print_bridge.bat',
  'stop_print_bridge.ps1',
  'PRINT_BRIDGE_CHECKLIST.md',
  'update_print_bridge.ps1'
)

try {
  Write-UpdateLog "Updater started. parent=$ParentPid source=$sourceRoot target=$targetRoot"
  if (-not (Test-Path -LiteralPath $sourceExe -PathType Leaf)) {
    throw "Update executable was not found: $sourceExe"
  }
  New-Item -ItemType Directory -Path $targetRoot -Force | Out-Null

  $parent = Get-Process -Id $ParentPid -ErrorAction SilentlyContinue
  if ($parent) {
    try {
      Wait-Process -Id $ParentPid -Timeout 45 -ErrorAction Stop
    } catch {
      Write-UpdateLog "Parent did not exit in time; stopping it before replacement."
      Stop-Process -Id $ParentPid -Force -ErrorAction SilentlyContinue
      Start-Sleep -Milliseconds 800
    }
  }

  Remove-Item -LiteralPath $tempExe -Force -ErrorAction SilentlyContinue
  Copy-Item -LiteralPath $sourceExe -Destination $tempExe -Force
  Move-Item -LiteralPath $tempExe -Destination $targetExe -Force

  foreach ($name in $supportFiles) {
    $sourceFile = Join-Path $sourceRoot $name
    if (Test-Path -LiteralPath $sourceFile -PathType Leaf) {
      Copy-Item -LiteralPath $sourceFile -Destination (Join-Path $targetRoot $name) -Force
    }
  }

  # 예전 버전명이 붙은 실행 파일이 안정 설치 폴더에 남아 있으면 제거한다.
  Get-ChildItem -LiteralPath $targetRoot -Filter 'xmath-print-bridge*.exe' -File -ErrorAction SilentlyContinue |
    Where-Object { [System.IO.Path]::GetFullPath($_.FullName) -ne [System.IO.Path]::GetFullPath($targetExe) } |
    Remove-Item -Force -ErrorAction SilentlyContinue

  $canonicalRunValue = 'xmath Print Bridge'
  $runCommand = '"{0}" --autorun' -f $targetExe
  $shouldRegisterRun = $false
  $configPath = Join-Path $targetRoot 'config.json'
  if (Test-Path -LiteralPath $configPath -PathType Leaf) {
    try {
      $config = Get-Content -LiteralPath $configPath -Raw -Encoding UTF8 | ConvertFrom-Json
      $autoRaw = $config.auto_start_on_launch
      $autoEnabled = $false
      if ($autoRaw -is [bool]) {
        $autoEnabled = [bool]$autoRaw
      } else {
        $autoEnabled = @('1', 'true', 'yes', 'on', 'y') -contains ([string]$autoRaw).Trim().ToLower()
      }
      $hasPlainToken = -not [string]::IsNullOrWhiteSpace([string]$config.device_token)
      $hasProtectedToken = -not [string]::IsNullOrWhiteSpace([string]$config.device_token_protected)
      $hasDeviceToken = $hasPlainToken -or $hasProtectedToken
      $shouldRegisterRun = $autoEnabled -and $hasDeviceToken
    } catch {
      Write-UpdateLog "Could not read startup preference from config; automatic Run registration skipped. $($_.Exception.Message)"
    }
  }

  if ($DryRun) {
    Write-UpdateLog "Dry-run update files installed successfully; startupRegistration=$shouldRegisterRun; startup changes and restart skipped."
    exit 0
  }

  $runKey = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Run'
  New-Item -Path $runKey -Force | Out-Null

  # xmath 프린트브릿지를 가리키는 과거 이름의 Run 항목은 하나로 합친다.
  $runProps = Get-ItemProperty -Path $runKey
  foreach ($prop in $runProps.PSObject.Properties) {
    if ($prop.Name -like 'PS*') { continue }
    $value = [string]$prop.Value
    if ($prop.Name -ne $canonicalRunValue -and $value.ToLower().Contains('xmath-print-bridge')) {
      Remove-ItemProperty -Path $runKey -Name $prop.Name -ErrorAction SilentlyContinue
      Write-UpdateLog "Removed legacy Run entry: $($prop.Name)"
    }
  }
  if ($shouldRegisterRun) {
    New-ItemProperty -Path $runKey -Name $canonicalRunValue -Value $runCommand -PropertyType String -Force | Out-Null
  } else {
    Remove-ItemProperty -Path $runKey -Name $canonicalRunValue -ErrorAction SilentlyContinue
  }

  # 과거 버전의 시작프로그램 바로가기가 남아 있으면 Run 항목과 중복되므로 정리한다.
  $startupDir = [Environment]::GetFolderPath('Startup')
  if ($startupDir -and (Test-Path -LiteralPath $startupDir)) {
    Get-ChildItem -LiteralPath $startupDir -File -ErrorAction SilentlyContinue |
      Where-Object { $_.BaseName.ToLower().Contains('xmath') -and $_.BaseName.ToLower().Contains('bridge') } |
      ForEach-Object {
        Write-UpdateLog "Removed legacy Startup item: $($_.FullName)"
        Remove-Item -LiteralPath $_.FullName -Force -ErrorAction SilentlyContinue
      }
  }

  Write-UpdateLog "Update files installed successfully. Restarting stable executable."
  Start-Process -FilePath $targetExe -ArgumentList '--autorun' -WorkingDirectory $targetRoot -WindowStyle Hidden
  Write-UpdateLog 'Updated bridge process started.'
  exit 0
} catch {
  Write-UpdateLog "Update failed: $($_.Exception.Message)"
  Remove-Item -LiteralPath $tempExe -Force -ErrorAction SilentlyContinue
  if (Test-Path -LiteralPath $targetExe -PathType Leaf) {
    try {
      Start-Process -FilePath $targetExe -ArgumentList '--autorun' -WorkingDirectory $targetRoot -WindowStyle Hidden
      Write-UpdateLog 'Previous stable bridge was restarted after update failure.'
    } catch {
      Write-UpdateLog "Failed to restart previous bridge: $($_.Exception.Message)"
    }
  }
  exit 1
}
