[CmdletBinding()]
param()

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

$repositoryRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..\..'))
$wrapper = Join-Path $repositoryRoot 'scripts\Invoke-LegacyPackageAppearanceSmoke.ps1'
$harness = Join-Path $repositoryRoot 'scripts\Test-LegacyPackageAppearanceSmoke.mjs'
foreach ($path in @($wrapper, $harness)) {
    if (-not [IO.File]::Exists($path)) { throw "Missing appearance smoke file: $path" }
}

$tokens = $null
$errors = $null
[void][Management.Automation.Language.Parser]::ParseFile(
    $wrapper,
    [ref]$tokens,
    [ref]$errors)
if (@($errors).Count -ne 0) { throw 'PowerShell rejected the appearance wrapper.' }

$node = Join-Path $env:USERPROFILE `
    '.cache\codex-runtimes\codex-primary-runtime\dependencies\node\bin\node.exe'
if (-not [IO.File]::Exists($node)) {
    $node = (Get-Command node.exe -CommandType Application -ErrorAction Stop |
        Select-Object -First 1).Source
}
& $node --check $harness
if ($LASTEXITCODE -ne 0) { throw 'Node rejected the appearance harness.' }

$auditJson = & powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass `
    -File $wrapper -StaticAudit
if ($LASTEXITCODE -ne 0) { throw 'The appearance static audit failed.' }
$audit = $auditJson | ConvertFrom-Json
if ([string]$audit.result -cne 'PASS' -or
    [string]$audit.profile -cne 'operator-appearance-persistence' -or
    [string]$audit.packageFlavor -cne 'DebugAppX' -or
    [int]$audit.launchCount -ne 2 -or
    [int]$audit.phaseCount -ne 2 -or
    [int]$audit.physicalSettingsClickCount -ne 2 -or
    [int]$audit.physicalSelectCount -ne 6 -or
    [int]$audit.inputRetryCount -ne 0 -or
    $audit.rawBaselineRecovery -ne $true -or
    $audit.packageForceTerminationAllowed -ne $false -or
    $audit.sendInputClickAvailable -ne $true -or
    $audit.sendInputSelectKeysAvailable -ne $true -or
    [int]$audit.inputStructureBytes -ne
        [int]$audit.expectedInputStructureBytes -or
    [int]$audit.inputStructureBytes -ne $(if ([IntPtr]::Size -eq 8) { 40 } else { 28 }) -or
    $audit.inputStructureSizeValidated -ne $true) {
    throw 'The appearance audit does not expose the exact two-launch input contract.'
}

$wrapperText = [IO.File]::ReadAllText($wrapper)
$harnessText = [IO.File]::ReadAllText($harness)
foreach ($token in @(
    '-BuildFlavor DebugAppX',
    '-DefinitionsOnly',
    'Start-ExactAppearanceApplication $registration 1',
    'Start-ExactAppearanceApplication $registration 2',
    'Restore-ExactBaselineSettings',
    '[FieldOffset(0)] public MouseInput Mouse',
    '[FieldOffset(0)] public HardwareInput Hardware',
    'IntPtr.Size == 8 ? 40 : 28',
    'operatorSettingsOriginallyAbsent',
    'startWorkspaceBehaviorVerifiedBeforeInput -ne $true',
    'The application was intentionally left open')) {
    if (-not $wrapperText.Contains($token)) { throw "Missing wrapper token: $token" }
}
foreach ($token in @(
    'persisted-appearance-after-relaunch',
    'persisted start workspace behavior',
    'snapshot.dom.activeWorkspace === expectedStartupWorkspace',
    'event.isTrusted === true',
    'trustedChange: true',
    'physicalKeyCounts:',
    'A native HTML <select> popup consumes Home/ArrowDown/Enter',
    'no input was retried')) {
    if (-not $harnessText.Contains($token)) { throw "Missing harness token: $token" }
}
if ($harnessText -match
        'postMessage\s*\(\s*\{\s*type:\s*["'']set-operator-appearance' -or
    $harnessText.Contains('rpc("Input.dispatchMouseEvent"') -or
    $harnessText.Contains('rpc("Input.dispatchKeyEvent"') -or
    $harnessText.Contains('trustedKeyDowns.length >= expectedKeyCalls') -or
    $wrapperText.Contains('trustedKeyDownCount -lt') -or
    $wrapperText -match '(?im)^\s*(?:Stop-Process|taskkill)\b' -or
    $wrapperText -match '(?i)C:\\Users\\[^\\]+') {
    throw 'The appearance smoke contains a synthetic input or unsafe host contract.'
}

[pscustomobject]@{
    result = 'PASS'
    launches = 2
    physicalSettingsClicks = 2
    physicalSelects = 6
    persistenceRelaunches = 1
    exactRawRestores = 1
    inputRetries = 0
} | ConvertTo-Json -Compress
