[CmdletBinding()]
param(
  [Parameter(Mandatory=$true)][string]$CoreScript,
  [Parameter(Mandatory=$true)][string]$StatusFile,
  [Parameter(Mandatory=$true)][string]$EventFile,
  [Parameter(Mandatory=$true)][string]$InputFile,
  [Parameter(Mandatory=$true)][string]$CancelFile,
  [Parameter(Mandatory=$true)][string]$SessionFile,
  [Parameter(Mandatory=$true)][string]$LogFile,
  [switch]$SkipProductionDeploy,
  [switch]$SelfTest,
  [string]$SelfTestFailAt = ''
)

Set-StrictMode -Version 2.0
$ErrorActionPreference = 'Stop'
$TargetVersion = '1.43.0'
$UpdaterVersion = '3.4.0'

function Get-DefaultSteps {
  return @(
    [ordered]@{id='package';title='Paket prüfen';state='pending'},
    [ordered]@{id='tools';title='System prüfen';state='pending'},
    [ordered]@{id='github';title='GitHub verbinden';state='pending'},
    [ordered]@{id='production';title='Zielzustand erkennen';state='pending'},
    [ordered]@{id='workspace';title='Payload sicher vorbereiten';state='pending'},
    [ordered]@{id='tests';title='Vollständig testen';state='pending'},
    [ordered]@{id='pullrequest';title='Pull Request abgleichen';state='pending'},
    [ordered]@{id='merge';title='Finalen Head prüfen und mergen';state='pending'},
    [ordered]@{id='deploy';title='Coolify deployen';state='pending'},
    [ordered]@{id='verify';title='Produktion bestätigen';state='pending'}
  )
}

function Append-HostLog([string]$Level,[string]$Message) {
  try {
    $parent = Split-Path -Parent $LogFile
    if ($parent) { New-Item -ItemType Directory -Path $parent -Force | Out-Null }
    $line = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss.fff') [$Level] $Message$([Environment]::NewLine)"
    [IO.File]::AppendAllText($LogFile,$line,(New-Object Text.UTF8Encoding($false)))
  } catch {}
}

function Write-HostStatus([string]$State,[string]$Phase,[string]$Detail,[string]$ErrorText='',[string]$Remediation='') {
  try {
    $percent = 1
    if ($State -in @('failed','cancelled','success')) { $percent = 100 }
    $payload = [ordered]@{
      version=$TargetVersion
      updaterVersion=$UpdaterVersion
      percent=$percent
      phase=$Phase
      detail=$Detail
      state=$State
      error=$ErrorText
      remediation=$Remediation
      updatedAt=(Get-Date).ToString('o')
      logFile=$LogFile
      sessionFile=$SessionFile
      steps=(Get-DefaultSteps)
      request=$null
    } | ConvertTo-Json -Depth 8
    $parent = Split-Path -Parent $StatusFile
    if ($parent) { New-Item -ItemType Directory -Path $parent -Force | Out-Null }
    $tmp = "$StatusFile.$PID.host.tmp"
    [IO.File]::WriteAllText($tmp,$payload,(New-Object Text.UTF8Encoding($false)))
    Move-Item -LiteralPath $tmp -Destination $StatusFile -Force
  } catch {
    Append-HostLog 'HOST-ERROR' "Status konnte nicht geschrieben werden: $($_.Exception.ToString())"
  }
}

try {
  foreach($path in @($StatusFile,$EventFile,$InputFile,$CancelFile,$SessionFile,$LogFile)) {
    $parent = Split-Path -Parent $path
    if ($parent) { New-Item -ItemType Directory -Path $parent -Force | Out-Null }
  }
  if (-not (Test-Path -LiteralPath $CoreScript -PathType Leaf)) {
    throw "Worker-Core fehlt: $CoreScript"
  }

  Append-HostLog 'HOST' "Worker-Host $UpdaterVersion gestartet. Core: $CoreScript"
  Write-HostStatus 'running' 'PowerShell-Parserprüfung' 'Der Worker-Kern wird vor der Ausführung mit dem echten PowerShell-Parser geprüft.'

  $parserTokens = $null
  $parserErrors = $null
  [void][System.Management.Automation.Language.Parser]::ParseFile($CoreScript,[ref]$parserTokens,[ref]$parserErrors)
  if ($parserErrors -and $parserErrors.Count -gt 0) {
    $details = @($parserErrors | ForEach-Object {
      "{0}:{1}:{2} {3}" -f $_.Extent.File,$_.Extent.StartLineNumber,$_.Extent.StartColumnNumber,$_.Message
    }) -join [Environment]::NewLine
    throw "PowerShell-Parserprüfung des Worker-Kerns fehlgeschlagen.$([Environment]::NewLine)$details"
  }
  Append-HostLog 'HOST' 'PowerShell-Parserprüfung des Worker-Kerns erfolgreich.'
  Write-HostStatus 'running' 'Worker wird gestartet' 'Der geprüfte Worker-Kern wird geladen.'

  $invokeParams = @{
    StatusFile=$StatusFile
    EventFile=$EventFile
    InputFile=$InputFile
    CancelFile=$CancelFile
    SessionFile=$SessionFile
    LogFile=$LogFile
  }
  if ($SkipProductionDeploy) { $invokeParams.SkipProductionDeploy = $true }
  if ($SelfTest) { $invokeParams.SelfTest = $true }
  if ($SelfTestFailAt) { $invokeParams.SelfTestFailAt = $SelfTestFailAt }

  & $CoreScript @invokeParams

  $terminal = $false
  $stateName = ''
  if (Test-Path -LiteralPath $StatusFile) {
    try {
      $final = Get-Content -LiteralPath $StatusFile -Raw -Encoding UTF8 | ConvertFrom-Json
      $stateName = [string]$final.state
      $terminal = $stateName -in @('success','failed','cancelled')
    } catch {
      Append-HostLog 'HOST-ERROR' "Abschlussstatus ist nicht lesbar: $($_.Exception.Message)"
    }
  }

  if (-not $terminal) {
    $message = 'Der Update-Kern wurde beendet, ohne einen terminalen Status zu schreiben.'
    Append-HostLog 'HOST-ERROR' $message
    Write-HostStatus 'failed' 'Update-Kern unvollständig beendet' $message $message 'Das Protokoll enthält jetzt die vollständige Start- und Worker-Diagnose. Es wurden keine stillen Fehler verworfen.'
  } else {
    Append-HostLog 'HOST' "Worker-Core regulär beendet. Status: $stateName"
  }
  exit 0
}
catch {
  $full = $_.Exception.ToString()
  $message = $_.Exception.Message
  Append-HostLog 'HOST-FATAL' $full
  Write-HostStatus 'failed' 'Worker konnte nicht initialisiert werden' $message $full 'Der Fehler entstand vor oder beim Laden des Worker-Kerns. Protokoll öffnen zeigt die vollständige PowerShell-Ausnahme einschließlich Datei und Zeile.'
  try { [Console]::Error.WriteLine($full) } catch {}
  Start-Sleep -Milliseconds 350
  exit 1
}
