FilterBox/Write-SRxJsonCustomization.ps1

function Write-SRxJsonCustomization {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)] $Connection,
        [Parameter(Mandatory)] [int]$Scope,
        [Parameter(Mandatory=$false)] [int]$Optype = -1,
        [Parameter(Mandatory=$false)] [string]$Environment = '',
        [Parameter(Mandatory=$false)] [string]$Design = '',
        [Parameter(Mandatory=$false)] [string]$TermID = '',
        [Parameter(Mandatory)] [string]$ContainerName,
        [Parameter(Mandatory)] [string]$Operation,
        [Parameter(Mandatory=$false)] [hashtable]$Props = @{}
    )

    $result = [pscustomobject]@{ Success=$false; Error=$null; ContainerId=$null; CustomizationsId=$null }
    try {
        if ([string]::IsNullOrEmpty($TermID)) { throw "TermID is required for JSON write (scope $Scope)." }
        $siteTerm = Get-PnPTerm -Identity ([GUID]$TermID) -Connection $Connection -ErrorAction SilentlyContinue
        if ($null -eq $siteTerm) { throw "Hosting term $TermID not found (scope $Scope)." }
        Get-PnPProperty -ClientObject $siteTerm -Property CustomProperties -Connection $Connection | Out-Null

        $custId = $null
        try { $custId = $siteTerm.CustomProperties['ts_ProvisioningTemplate'] } catch {}
        $customizations = $null
        if ($custId) {
            $customizations = Get-PnPTerm -Identity ([GUID]$custId) -Connection $Connection -ErrorAction SilentlyContinue
        }
        if ($null -eq $customizations) {
            $customizations = Add-PnPTermToTerm -ParentTerm $siteTerm.Id -Name 'Customizations' -Connection $Connection
            $fresh = Get-PnPTerm -Identity $siteTerm.Id -Connection $Connection
            $fresh.SetCustomProperty('ts_ProvisioningTemplate', [string]$customizations.Id)
            Invoke-PnPQuery -RetryCount 5 -Connection $Connection
        }
        if ($null -eq $customizations) { throw "Could not resolve/create Customizations host under term $TermID." }
        $result.CustomizationsId = [string]$customizations.Id
        Get-PnPProperty -ClientObject $customizations -Property Terms -Connection $Connection | Out-Null
        $container = $null
        foreach ($t in $customizations.Terms) { if ([string]$t.Name -eq $ContainerName) { $container = $t; break } }

        if ($Operation -eq 'remove') {
            if ($container) { Remove-PnPTerm -Identity $container.Id -Force -Connection $Connection }
            $result.Success = $true
            return $result
        }

        $flat = @{}
        foreach ($k in @($Props.Keys)) {
            $v = [string]$Props[$k]
            if ($k -eq 'ts_CustomizationJson') {
                $chunked = Split-SRxJsonProperty -BaseKey 'ts_CustomizationJson' -Value $v
                foreach ($ck in $chunked.Keys) { $flat[[string]$ck] = [string]$chunked[$ck] }
            } else {
                $flat[[string]$k] = $v
            }
        }

        if (-not $container) {
            $container = Add-PnPTermToTerm -ParentTerm $customizations.Id -Name $ContainerName -CustomProperties $flat -Connection $Connection
            $result.ContainerId = [string]$container.Id
            $result.Success = $true
            return $result
        }
        else {
            $fresh = Get-PnPTerm -Identity $container.Id -Connection $Connection
            foreach ($k in $flat.Keys) { $fresh.SetCustomProperty([string]$k, [string]$flat[$k]) }
            Invoke-PnPQuery -RetryCount 5 -Connection $Connection
            $result.ContainerId = [string]$fresh.Id
            $result.Success = $true
            return $result
        }
    }
    catch {
        $result.Error = $_.Exception.Message
        return $result
    }
}