functions/private/Invoke-KlippyWebSocketWait.ps1

function Invoke-KlippyWebSocketWait {
    <#
    .SYNOPSIS
        Waits for a condition using WebSocket subscriptions.

    .DESCRIPTION
        Connects via WebSocket, subscribes to printer objects, and waits
        for a condition to be met based on status updates.

    .PARAMETER Printer
        The printer object.

    .PARAMETER Objects
        Hashtable of objects to subscribe to.
        Format: @{ object_name = $null } or @{ object_name = @("attr1", "attr2") }

    .PARAMETER Condition
        ScriptBlock that receives status updates and returns $true when condition is met.
        Receives the status hashtable as $args[0].

    .PARAMETER TimeoutSeconds
        Maximum time to wait. Default is 300 (5 minutes).

    .PARAMETER ProgressMessage
        Optional message for progress output.

    .PARAMETER OnProgress
        Optional ScriptBlock called on each status update for progress reporting.

    .EXAMPLE
        Invoke-KlippyWebSocketWait -Printer $printer -Objects @{print_stats=$null} `
            -Condition { $args[0].print_stats.state -eq 'complete' }

    .OUTPUTS
        The final status that matched the condition.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [PSCustomObject]$Printer,

        [Parameter(Mandatory = $true)]
        [hashtable]$Objects,

        [Parameter(Mandatory = $true)]
        [scriptblock]$Condition,

        [Parameter()]
        [ValidateRange(1, 3600)]
        [int]$TimeoutSeconds = 300,

        [Parameter()]
        [string]$ProgressMessage,

        [Parameter()]
        [scriptblock]$OnProgress
    )

    $ws = $null

    try {
        # Connect WebSocket
        $ws = New-KlippyWebSocketClient -Printer $Printer

        # Subscribe to objects
        Write-Verbose "Subscribing to: $($Objects.Keys -join ', ')"
        $initialStatus = $ws.Subscribe($Objects)

        # Check if condition is already met from initial status
        if ($initialStatus.status) {
            $normalized = ConvertTo-KlippyPascalCaseObject -InputObject $initialStatus.status
            if (& $Condition $initialStatus.status) {
                Write-Verbose "Condition already met from initial status"
                return $normalized
            }
        }

        # Wait for condition
        if ($ProgressMessage) {
            Write-Host $ProgressMessage -NoNewline
        }

        # Build progress callback
        $progressCallback = {
            param($status)
            if ($OnProgress) {
                & $OnProgress $status
            }
            if ($ProgressMessage) {
                Write-Host "." -NoNewline
            }
        }

        # Call WaitForMessage with positional parameters (ScriptMethods don't support named params)
        $result = $ws.WaitForMessage($Condition, $TimeoutSeconds, $progressCallback)

        if ($ProgressMessage) {
            Write-Host " Done"
        }

        return ConvertTo-KlippyPascalCaseObject -InputObject $result
    }
    finally {
        if ($ws) {
            $ws.Close()
        }
    }
}