Pax8API/Public/Find-Pax8Product.ps1

function Find-Pax8Product {
    [CmdletBinding()]
    param (
        [string]$Search,

        [string]$VendorName,

        [ValidateRange(0, [int]::MaxValue)]
        [int]$Page = 0,

        [ValidateRange(1, 200)]
        [int]$Size = 50,

        [ValidateSet('name', 'vendor')]
        [string]$Sort = 'name',

        [ValidateSet('asc', 'desc')]
        [string]$Direction = 'asc',

        [string[]]$MatchProperty = @('name', 'vendorName', 'sku', 'vendorSku', 'altVendorSku'),

        [switch]$IncludeDescription,

        [switch]$Exact,

        [switch]$ForceClientSide,

        [switch]$NoClientSideFallback,

        [switch]$All,

        [switch]$Raw
    )

    $queryParameters = @{}
    if ($VendorName) { $queryParameters.VendorName = $VendorName }
    if ($Sort) { $queryParameters.Sort = $Sort }
    if ($Direction) { $queryParameters.Direction = $Direction }

    if (-not $ForceClientSide) {
        $serverParameters = @{}
        foreach ($entry in $queryParameters.GetEnumerator()) {
            $serverParameters[$entry.Key] = $entry.Value
        }
        if ($Search) { $serverParameters.Search = $Search }

        if ($All) {
            $serverProducts = @(Get-Pax8Product @serverParameters -All)
            if ($serverProducts.Count -gt 0 -or $NoClientSideFallback -or -not $Search) {
                if ($Raw) {
                    return [pscustomobject]@{
                        content = $serverProducts
                        page = [pscustomobject]@{
                            size = $serverProducts.Count
                            totalElements = $serverProducts.Count
                            totalPages = 1
                            number = 0
                        }
                        clientSideFallback = $false
                    }
                }

                return $serverProducts
            }
        } else {
            $serverParameters.Page = $Page
            $serverParameters.Size = $Size
            $serverResponse = Get-Pax8Product @serverParameters -Raw
            $serverProducts = if ($serverResponse -and $serverResponse.PSObject.Properties['content']) {
                if ($null -eq $serverResponse.content) { @() } else { @($serverResponse.content) }
            } elseif ($serverResponse -and $serverResponse.PSObject.Properties['page'] -and $serverResponse.page.PSObject.Properties['totalElements'] -and [int]$serverResponse.page.totalElements -eq 0) {
                @()
            } elseif ($serverResponse) {
                @($serverResponse)
            } else {
                @()
            }
            if ($serverProducts.Count -gt 0 -or $NoClientSideFallback -or -not $Search) {
                if ($Raw) {
                    return $serverResponse
                }

                return $serverProducts
            }
        }
    }

    if ($NoClientSideFallback) {
        return
    }

    $fallbackParameters = @{}
    if ($VendorName) { $fallbackParameters.VendorName = $VendorName }

    Write-Verbose "Pax8 product search returned no server-side matches. Falling back to client-side catalog matching."
    $catalog = @(Get-Pax8Product @fallbackParameters -All)
    $properties = @($MatchProperty)
    if ($IncludeDescription) {
        $properties += 'shortDescription', 'description'
    }

    $matches = foreach ($product in $catalog) {
        if (Test-Pax8ProductMatch -Product $product -Search $Search -Property $properties -Exact:$Exact) {
            [pscustomobject]@{
                Product = $product
                Score = Get-Pax8ProductSearchScore -Product $product -Search $Search
            }
        }
    }

    $sortedMatches = $matches | Sort-Object Score, @{ Expression = { $_.Product.name }; Ascending = ($Direction -ne 'desc') }
    if ($Sort -eq 'vendor') {
        $sortedMatches = $matches | Sort-Object Score, @{ Expression = { $_.Product.vendorName }; Ascending = ($Direction -ne 'desc') }, @{ Expression = { $_.Product.name }; Ascending = $true }
    }

    $products = @($sortedMatches | ForEach-Object { $_.Product })
    $totalElements = $products.Count
    if (-not $All) {
        $products = @($products | Select-Object -Skip ($Page * $Size) -First $Size)
    }

    if ($Raw) {
        return [pscustomobject]@{
            content = $products
            page = [pscustomobject]@{
                size = if ($All) { $products.Count } else { $Size }
                totalElements = $totalElements
                totalPages = if ($All -or $Size -le 0) { 1 } else { [Math]::Ceiling($totalElements / $Size) }
                number = $Page
            }
            clientSideFallback = $true
        }
    }

    $products
}