functions/public/Test-KlippyPrinterConnection.ps1

function Test-KlippyPrinterConnection {
    <#
    .SYNOPSIS
        Tests connectivity to a Klipper printer via Moonraker.

    .DESCRIPTION
        Tests HTTP connectivity to the Moonraker API and optionally verifies
        that Klipper is running and ready.

    .PARAMETER Uri
        The Moonraker URI to test. Used for testing before adding a printer.

    .PARAMETER ApiKey
        Optional API key for authentication.

    .PARAMETER Id
        The unique identifier of a registered printer to test.

    .PARAMETER PrinterName
        The friendly name of a registered printer to test.

    .PARAMETER InputObject
        A printer object from pipeline input.

    .PARAMETER Full
        Perform a full check including Klipper readiness verification.

    .PARAMETER Timeout
        Connection timeout in seconds. Default is 10.

    .EXAMPLE
        Test-KlippyPrinterConnection -Uri "http://192.168.1.100:7125"
        Tests basic connectivity to the specified Moonraker instance.

    .EXAMPLE
        Test-KlippyPrinterConnection -PrinterName "MyPrinter" -Full
        Tests connectivity and Klipper readiness for a registered printer.

    .EXAMPLE
        Get-KlippyPrinter | Test-KlippyPrinterConnection -Full
        Tests all registered printers via pipeline.

    .OUTPUTS
        PSCustomObject with test results.
    #>

    [CmdletBinding(DefaultParameterSetName = 'ByUri')]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory = $true, ParameterSetName = 'ByUri', Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string]$Uri,

        [Parameter(ParameterSetName = 'ByUri')]
        [string]$ApiKey,

        [Parameter(Mandatory = $true, ParameterSetName = 'ById')]
        [ValidateNotNullOrEmpty()]
        [string]$Id,

        [Parameter(Mandatory = $true, ParameterSetName = 'ByName')]
        [ValidateNotNullOrEmpty()]
        [string]$PrinterName,

        [Parameter(Mandatory = $true, ParameterSetName = 'ByObject', ValueFromPipeline = $true)]
        [PSCustomObject]$InputObject,

        [Parameter()]
        [switch]$Full,

        [Parameter()]
        [ValidateRange(1, 300)]
        [int]$Timeout = 10
    )

    process {
        # Resolve printer if using registered printer
        $targetUri = $Uri
        $targetApiKey = $ApiKey
        $targetName = $null
        $targetId = $null

        if ($PSCmdlet.ParameterSetName -ne 'ByUri') {
            $resolveParams = @{}
            switch ($PSCmdlet.ParameterSetName) {
                'ById' { $resolveParams['Id'] = $Id }
                'ByName' { $resolveParams['PrinterName'] = $PrinterName }
                'ByObject' { $resolveParams['InputObject'] = $InputObject }
            }

            $printer = Resolve-KlippyPrinterTarget @resolveParams
            $targetUri = $printer.Uri
            $targetApiKey = $printer.ApiKey
            $targetName = $printer.PrinterName
            $targetId = $printer.Id
        }

        # Normalize URI (remove trailing slash)
        $targetUri = $targetUri.TrimEnd('/')

        # Build headers
        $headers = @{}
        if ($targetApiKey) {
            $headers['X-Api-Key'] = $targetApiKey
        }

        # Initialize result object
        $result = [PSCustomObject]@{
            PSTypeName         = 'KlippyCLI.ConnectionTestResult'
            Uri                = $targetUri
            PrinterId          = $targetId
            PrinterName        = $targetName
            MoonrakerReachable = $false
            MoonrakerVersion   = $null
            KlipperReady       = $null
            KlipperState       = $null
            ErrorMessage       = $null
            TestedAt           = [datetime]::UtcNow
        }

        # Test basic Moonraker connectivity
        try {
            Write-Verbose "Testing Moonraker connectivity at $targetUri/server/info"

            $invokeParams = @{
                Uri             = "$targetUri/server/info"
                Method          = 'GET'
                Headers         = $headers
                TimeoutSec      = $Timeout
                ErrorAction     = 'Stop'
            }

            $serverInfo = Invoke-RestMethod @invokeParams
            $result.MoonrakerReachable = $true
            $result.MoonrakerVersion = $serverInfo.result.moonraker_version

            Write-Verbose "Moonraker reachable. Version: $($result.MoonrakerVersion)"
        }
        catch {
            $result.MoonrakerReachable = $false
            $result.ErrorMessage = "Moonraker connection failed: $($_.Exception.Message)"
            Write-Verbose $result.ErrorMessage
            return $result
        }

        # Test Klipper readiness if -Full specified
        if ($Full) {
            try {
                Write-Verbose "Testing Klipper readiness at $targetUri/printer/info"

                $invokeParams = @{
                    Uri             = "$targetUri/printer/info"
                    Method          = 'GET'
                    Headers         = $headers
                    TimeoutSec      = $Timeout
                    ErrorAction     = 'Stop'
                }

                $printerInfo = Invoke-RestMethod @invokeParams
                $klipperState = $printerInfo.result.state

                $result.KlipperState = $klipperState
                $result.KlipperReady = ($klipperState -eq 'ready')

                Write-Verbose "Klipper state: $klipperState"

                if (-not $result.KlipperReady) {
                    $stateMessage = $printerInfo.result.state_message
                    if ($stateMessage) {
                        $result.ErrorMessage = "Klipper not ready: $stateMessage"
                    }
                    else {
                        $result.ErrorMessage = "Klipper not ready. State: $klipperState"
                    }
                }
            }
            catch {
                $result.KlipperReady = $false
                $result.ErrorMessage = "Klipper check failed: $($_.Exception.Message)"
                Write-Verbose $result.ErrorMessage
            }
        }

        return $result
    }
}