functions/public/Set-KlippyPrinter.ps1

function Set-KlippyPrinter {
    <#
    .SYNOPSIS
        Modifies an existing Klipper printer in the local registry.

    .DESCRIPTION
        Updates properties of a registered printer configuration.
        Can update name, URI, API key, description, and default status.

    .PARAMETER Id
        The unique identifier of the printer to modify.

    .PARAMETER PrinterName
        The current name of the printer to modify.

    .PARAMETER InputObject
        A printer object from pipeline input.

    .PARAMETER NewName
        The new friendly name for the printer.

    .PARAMETER Uri
        The new Moonraker API URI.

    .PARAMETER ApiKey
        The new API key. Use empty string to clear.

    .PARAMETER Description
        The new description. Use empty string to clear.

    .PARAMETER IsDefault
        Set this printer as the default.

    .PARAMETER ClearApiKey
        Clear the API key.

    .PARAMETER ClearDescription
        Clear the description.

    .EXAMPLE
        Set-KlippyPrinter -PrinterName "Voron" -NewName "Voron 2.4"
        Renames the printer from "Voron" to "Voron 2.4".

    .EXAMPLE
        Set-KlippyPrinter -PrinterName "Ender3" -IsDefault
        Sets the "Ender3" printer as default.

    .EXAMPLE
        Get-KlippyPrinter -PrinterName "Voron" | Set-KlippyPrinter -Uri "http://192.168.1.200:7125"
        Updates the URI via pipeline.

    .OUTPUTS
        PSCustomObject - The updated printer object.
    #>

    [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'ByName')]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory = $true, ParameterSetName = 'ById')]
        [ValidateNotNullOrEmpty()]
        [string]$Id,

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

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

        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [ValidatePattern('^[a-zA-Z0-9_\-\.\s]+$')]
        [string]$NewName,

        [Parameter()]
        [ValidateScript({
            if ([string]::IsNullOrEmpty($_)) { return $true }
            $uri = $null
            if ([System.Uri]::TryCreate($_, [System.UriKind]::Absolute, [ref]$uri)) {
                if ($uri.Scheme -in @('http', 'https')) {
                    return $true
                }
                throw "Uri must use http or https scheme."
            }
            throw "Invalid URI format."
        })]
        [string]$Uri,

        [Parameter()]
        [AllowEmptyString()]
        [string]$ApiKey,

        [Parameter()]
        [AllowEmptyString()]
        [string]$Description,

        [Parameter()]
        [switch]$IsDefault,

        [Parameter()]
        [switch]$ClearApiKey,

        [Parameter()]
        [switch]$ClearDescription
    )

    process {
        # Read all printers
        $printers = Read-KlippyPrinterRegistry

        # Resolve target printer
        $resolveParams = @{ Printers = $printers }
        switch ($PSCmdlet.ParameterSetName) {
            'ById' { $resolveParams['Id'] = $Id }
            'ByName' { $resolveParams['PrinterName'] = $PrinterName }
            'ByObject' { $resolveParams['InputObject'] = $InputObject }
        }

        $targetPrinter = Resolve-KlippyPrinterTarget @resolveParams

        # Find the printer in the collection (by reference)
        $printerToUpdate = $printers | Where-Object { $_.Id -eq $targetPrinter.Id }

        if (-not $printerToUpdate) {
            throw "Printer not found in registry."
        }

        $changes = @()

        # Check for new name uniqueness
        if ($NewName -and $NewName -ine $printerToUpdate.PrinterName) {
            $existingWithName = $printers | Where-Object { $_.PrinterName -ieq $NewName -and $_.Id -ne $printerToUpdate.Id }
            if ($existingWithName) {
                throw "A printer with name '$NewName' already exists."
            }
            $changes += "Name: $($printerToUpdate.PrinterName) -> $NewName"
            $printerToUpdate.PrinterName = $NewName
        }

        # Update URI
        if ($PSBoundParameters.ContainsKey('Uri') -and $Uri) {
            $normalizedUri = $Uri.TrimEnd('/')
            if ($normalizedUri -ne $printerToUpdate.Uri) {
                $changes += "Uri: $($printerToUpdate.Uri) -> $normalizedUri"
                $printerToUpdate.Uri = $normalizedUri
            }
        }

        # Update API Key
        if ($ClearApiKey) {
            if ($printerToUpdate.ApiKey) {
                $changes += "ApiKey: cleared"
                $printerToUpdate.ApiKey = $null
            }
        }
        elseif ($PSBoundParameters.ContainsKey('ApiKey')) {
            if ($ApiKey -ne $printerToUpdate.ApiKey) {
                $changes += "ApiKey: updated"
                $printerToUpdate.ApiKey = if ([string]::IsNullOrEmpty($ApiKey)) { $null } else { $ApiKey }
            }
        }

        # Update Description
        if ($ClearDescription) {
            if ($printerToUpdate.Description) {
                $changes += "Description: cleared"
                $printerToUpdate.Description = $null
            }
        }
        elseif ($PSBoundParameters.ContainsKey('Description')) {
            if ($Description -ne $printerToUpdate.Description) {
                $changes += "Description: updated"
                $printerToUpdate.Description = if ([string]::IsNullOrEmpty($Description)) { $null } else { $Description }
            }
        }

        # Update default status
        if ($IsDefault -and -not $printerToUpdate.IsDefault) {
            # Clear existing default
            foreach ($p in $printers) {
                if ($p.IsDefault -and $p.Id -ne $printerToUpdate.Id) {
                    $p.IsDefault = $false
                    $p.ModifiedAt = [datetime]::UtcNow
                }
            }
            $printerToUpdate.IsDefault = $true
            $changes += "IsDefault: true"
        }

        if ($changes.Count -eq 0) {
            Write-Verbose "No changes to apply."
            return $printerToUpdate
        }

        $changesDescription = $changes -join ', '
        $targetDescription = $printerToUpdate.PrinterName

        if ($PSCmdlet.ShouldProcess($targetDescription, "Update printer ($changesDescription)")) {
            $printerToUpdate.ModifiedAt = [datetime]::UtcNow

            Write-KlippyPrinterRegistry -Printers $printers

            Write-Verbose "Printer '$($printerToUpdate.PrinterName)' updated: $changesDescription"

            return $printerToUpdate
        }
    }
}