functions/public/Save-KlippyWebcamSnapshot.ps1

function Save-KlippyWebcamSnapshot {
    <#
    .SYNOPSIS
        Saves a webcam snapshot from a Klipper printer.

    .DESCRIPTION
        Downloads a snapshot image from a configured webcam and saves it to a file.

    .PARAMETER Id
        The unique identifier of the printer.

    .PARAMETER PrinterName
        The friendly name of the printer.

    .PARAMETER InputObject
        A webcam object from pipeline input.

    .PARAMETER WebcamName
        The name of the webcam to capture from.

    .PARAMETER Path
        The file path to save the snapshot. If not specified, saves to current directory
        with a timestamp-based filename.

    .PARAMETER Force
        Overwrite existing file without prompting.

    .EXAMPLE
        Save-KlippyWebcamSnapshot
        Saves a snapshot from the first webcam to the current directory.

    .EXAMPLE
        Save-KlippyWebcamSnapshot -WebcamName "main_camera" -Path "C:\snapshots\print.jpg"
        Saves a snapshot from a specific webcam to a specific path.

    .EXAMPLE
        Get-KlippyWebcam | Save-KlippyWebcamSnapshot -Path "C:\snapshots"
        Saves snapshots from all webcams to a folder.

    .OUTPUTS
        System.IO.FileInfo object for the saved file.
    #>

    [CmdletBinding(SupportsShouldProcess)]
    [OutputType([System.IO.FileInfo])]
    param(
        [Parameter(ParameterSetName = 'ById')]
        [ValidateNotNullOrEmpty()]
        [string]$Id,

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

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

        [Parameter(ParameterSetName = 'ById')]
        [Parameter(ParameterSetName = 'ByName')]
        [string]$WebcamName,

        [Parameter()]
        [string]$Path,

        [Parameter()]
        [switch]$Force
    )

    process {
        $webcam = $null
        $printer = $null

        # Handle webcam object from pipeline
        if ($InputObject -and $InputObject.PSTypeName -eq 'KlippyCLI.Webcam') {
            $webcam = $InputObject
            $printer = [PSCustomObject]@{
                Id = $InputObject.PrinterId
                PrinterName = $InputObject.PrinterName
            }
        }
        else {
            # Resolve printer
            $resolveParams = @{}
            if ($Id) { $resolveParams['Id'] = $Id }
            elseif ($PrinterName) { $resolveParams['PrinterName'] = $PrinterName }
            elseif ($InputObject) { $resolveParams['InputObject'] = $InputObject }

            $printer = Resolve-KlippyPrinterTarget @resolveParams

            # Get webcams
            $webcams = Get-KlippyWebcam -Id $printer.Id
            if (-not $webcams) {
                Write-Error "No webcams found on '$($printer.PrinterName)'."
                return
            }

            if ($WebcamName) {
                $webcam = $webcams | Where-Object { $_.Name -eq $WebcamName }
                if (-not $webcam) {
                    Write-Error "Webcam '$WebcamName' not found on '$($printer.PrinterName)'."
                    return
                }
            }
            else {
                # Use the first enabled webcam
                $webcam = $webcams | Where-Object { $_.Enabled } | Select-Object -First 1
                if (-not $webcam) {
                    $webcam = $webcams | Select-Object -First 1
                }
            }
        }

        if (-not $webcam.SnapshotUrl) {
            Write-Error "Webcam '$($webcam.Name)' does not have a snapshot URL configured."
            return
        }

        try {
            # Determine output path
            $outputPath = $Path
            if (-not $outputPath) {
                $timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
                $outputPath = Join-Path (Get-Location) "$($printer.PrinterName)_$($webcam.Name)_$timestamp.jpg"
            }
            elseif (Test-Path $outputPath -PathType Container) {
                # Path is a directory, generate filename
                $timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
                $outputPath = Join-Path $outputPath "$($printer.PrinterName)_$($webcam.Name)_$timestamp.jpg"
            }

            # Check if file exists
            if ((Test-Path $outputPath) -and -not $Force) {
                if (-not $PSCmdlet.ShouldProcess($outputPath, "Overwrite existing file")) {
                    return
                }
            }

            $action = "Save snapshot from '$($webcam.Name)'"
            if ($PSCmdlet.ShouldProcess($printer.PrinterName, $action)) {
                Write-Verbose "Downloading snapshot from: $($webcam.SnapshotUrl)"

                # Download the snapshot
                $webClient = [System.Net.WebClient]::new()
                try {
                    $webClient.DownloadFile($webcam.SnapshotUrl, $outputPath)
                }
                finally {
                    $webClient.Dispose()
                }

                $fileInfo = Get-Item $outputPath
                Write-Host "Saved snapshot to: $outputPath ($([math]::Round($fileInfo.Length / 1KB, 1)) KB)" -ForegroundColor Green

                Write-Output $fileInfo
            }
        }
        catch {
            Write-Error "Failed to save webcam snapshot from '$($printer.PrinterName)': $_"
        }
    }
}