internal/functions/Build-HydrationAssignmentPlan.ps1

function Build-HydrationAssignmentPlan {
    [CmdletBinding()]
    param (
        [string] $AssignmentsRootFolder,
        [hashtable] $PacEnvironment,
        [hashtable] $ScopeTable,
        [hashtable] $DeployedPolicyResources,
        [hashtable] $Assignments,
        [hashtable] $RoleAssignments,
        [hashtable] $AllAssignments,
        [hashtable] $ReplaceDefinitions,
        [hashtable] $PolicyRoleIds,
        [hashtable] $CombinedPolicyDetails,
        [hashtable] $DeprecatedHash,
        [System.Collections.Specialized.OrderedDictionary] $DetailedRecord,
        [switch] $ExtendedReporting
    )

    Write-Information "==================================================================================================="
    Write-Information "Processing Policy Assignments JSON files in folder '$AssignmentsRootFolder'"
    Write-Information "==================================================================================================="

    if($ExtendedReporting){
        $allAssignmentRecords = [ordered]@{}
        $rRoot = (Resolve-Path (Split-Path (Split-Path $AssignmentsRootFolder))).Path
    }
    
    $assignmentFiles = @()
    $assignmentFiles += Get-ChildItem -Path $AssignmentsRootFolder -Recurse -File -Filter "*.json"
    $assignmentFiles += Get-ChildItem -Path $AssignmentsRootFolder -Recurse -File -Filter "*.jsonc"
    $csvFiles = Get-ChildItem -Path $AssignmentsRootFolder -Recurse -File -Filter "*.csv"
    $parameterFilesCsv = @{}
    if ($assignmentFiles.Length -gt 0) {
        Write-Information "Number of Policy Assignment files = $($assignmentFiles.Length)"
        foreach ($csvFile in $csvFiles) {
            $parameterFilesCsv.Add($csvFile.Name, $csvFile.FullName)
        }
    }
    else {
        Write-Warning "No Policy Assignment files found! Deleting any Policy Assignments."
    }

    # Cache role assignments and definitions

    $deployedPolicyAssignments = $deployedPolicyResources.policyassignments.managed
    $deployedRoleAssignmentsByPrincipalId = $DeployedPolicyResources.roleAssignmentsByPrincipalId
    $deleteCandidates = $deployedPolicyAssignments.Clone()
    $roleDefinitions = $DeployedPolicyResources.roleDefinitions

    # Process each assignment file
    foreach ($assignmentFile in $assignmentFiles) {
        $Json = Get-Content -Path $assignmentFile.FullName -Raw -ErrorAction Stop

        $includedCloudEnvironments = ($Json | ConvertFrom-Json).epacCloudEnvironments
        if ($includedCloudEnvironments) {
            if ($pacEnvironment.cloud -notIn $includedCloudEnvironments) {
                continue
            }
        }
        if($ExtendedReporting){
            Remove-Variable fileRecord -ErrorAction SilentlyContinue
            $fileRecord = Get-DeepCloneAsOrderedHashtable -InputObject $DetailedRecord
            if(!(Test-Path $AssignmentsRootFolder)){
                Write-Error "No Assignments folder found at $AssignmentsRootFolder"
            }
            $relativePath = -join(".",$assignmentFile.FullName.Substring(($rRoot).Length))
            $fileRecord.Set_Item('fileRelativePath', $relativePath)
        }
        # Write-Information ""
        $assignmentObject = $null
        try {
            $assignmentObject = $Json | ConvertFrom-Json -Depth 100 -AsHashtable
        }
        catch {
            Write-Error "Assignment JSON file '$($assignmentFile.FullName)' is not valid." -ErrorAction Stop
        }
        # Remove-NullFields $assignmentObject

        # Collect all assignment definitions (values)
        $rootAssignmentDefinition = @{
            nodeName                       = "/"
            metadata                       = @{
                assignedBy = $PacEnvironment.deployedBy
            }
            assignment                     = @{
                append      = $false
                name        = ""
                displayName = ""
                description = ""
            }
            enforcementMode                = "Default"
            parameters                     = @{}
            additionalRoleAssignments      = [System.Collections.ArrayList]::new()
            requiredRoleAssignments        = $null
            nonComplianceMessages          = [System.Collections.ArrayList]::new()
            overrides                      = [System.Collections.ArrayList]::new()
            resourceSelectors              = [System.Collections.ArrayList]::new()
            hasErrors                      = $false
            hasOnlyNotSelectedEnvironments = $false
            ignoreBranch                   = $false
            managedIdentityLocation        = $PacEnvironment.managedIdentityLocation
            notScopesList                  = [System.Collections.ArrayList]::new()
            csvRowsValidated               = $false
        }

        $hasErrors, $assignmentsList = Build-AssignmentDefinitionNode `
            -PacEnvironment $PacEnvironment `
            -ScopeTable $ScopeTable `
            -ParameterFilesCsv $parameterFilesCsv `
            -DefinitionNode $assignmentObject `
            -AssignmentDefinition $rootAssignmentDefinition `
            -CombinedPolicyDetails $CombinedPolicyDetails `
            -PolicyRoleIds $PolicyRoleIds `
            -RoleDefinitions $roleDefinitions `
            -DeprecatedHash $DeprecatedHash

        if ($hasErrors) {
            Write-Error "Assignment definitions content errors" -ErrorAction Stop
        }
        $isUserAssignedAny = $false
        foreach ($assignment in $assignmentsList) {
            # Remove-NullFields $assignment
            $id = $assignment.id
            $AllAssignments[$id] = $assignment
            $displayName = $assignment.displayName
            $description = $assignment.description
            $metadata = $assignment.metadata
            $parameters = $assignment.parameters
            $policyDefinitionId = $assignment.policyDefinitionId
            $definitionVersion = $assignment.definitionVersion
            $scope = $assignment.scope
            $notScopes = $assignment.notScopes
            $enforcementMode = $assignment.enforcementMode
            $nonComplianceMessages = $assignment.nonComplianceMessages
            $overrides = $assignment.overrides
            $resourceSelectors = $assignment.resourceSelectors
            if ($deployedPolicyAssignments.ContainsKey($id)) {
                # Update and replace scenarios
                Remove-Variable deployedPolicyAssignment -ErrorAction SilentlyContinue
                $deployedPolicyAssignment = $deployedPolicyAssignments[$id]
                Remove-Variable deployedPolicyAssignmentProperties -ErrorAction SilentlyContinue
                $deployedPolicyAssignmentProperties = Get-PolicyResourceProperties $deployedPolicyAssignment
                $deleteCandidates.Remove($id) # do not delete

                $replacedDefinition = $ReplaceDefinitions.ContainsKey($policyDefinitionId)
                $changedPolicyDefinitionId = $policyDefinitionId -ne $deployedPolicyAssignmentProperties.policyDefinitionId
                $definitionVersionMatches = $true
                if ($definitionVersion) {
                    $definitionVersionMatches = $definitionVersion -eq $deployedPolicyAssignmentProperties.definitionVersion
                }
                $displayNameMatches = $displayName -eq $deployedPolicyAssignmentProperties.displayName
                $descriptionMatches = $description -eq $deployedPolicyAssignmentProperties.description
                Remove-Variable notScopesMatch -ErrorAction SilentlyContinue
                $notScopesMatch = Confirm-ObjectValueEqualityDeep `
                    $deployedPolicyAssignmentProperties.notScopes `
                    $notScopes
                $parametersMatch = Confirm-ParametersUsageMatches `
                    -ExistingParametersObj $deployedPolicyAssignmentProperties.parameters `
                    -DefinedParametersObj $parameters `
                    -CompareValueEntryForExistingParametersObj
                Remove-Variable metadataMatches -ErrorAction SilentlyContinue
                Remove-Variable changePacOwnerId -ErrorAction SilentlyContinue
                $metadataMatches, $changePacOwnerId = Confirm-MetadataMatches `
                    -ExistingMetadataObj $deployedPolicyAssignmentProperties.metadata `
                    -DefinedMetadataObj $metadata
                $enforcementModeMatches = $enforcementMode -eq $deployedPolicyAssignmentProperties.enforcementMode
                Remove-Variable nonComplianceMessagesMatches -ErrorAction SilentlyContinue
                $nonComplianceMessagesMatches = Confirm-ObjectValueEqualityDeep `
                    $deployedPolicyAssignmentProperties.nonComplianceMessages `
                    $nonComplianceMessages
                Remove-Variable overridesMatch -ErrorAction SilentlyContinue
                $overridesMatch = Confirm-ObjectValueEqualityDeep `
                    $deployedPolicyAssignmentProperties.overrides `
                    $overrides
                Remove-Variable resourceSelectorsMatch -ErrorAction SilentlyContinue
                $resourceSelectorsMatch = Confirm-ObjectValueEqualityDeep `
                    $deployedPolicyAssignmentProperties.resourceSelectors `
                    $resourceSelectors
                Remove-Variable identityStatus -ErrorAction SilentlyContinue
                $identityStatus = Build-AssignmentIdentityChanges `
                    -Existing $deployedPolicyAssignment `
                    -Assignment $assignment `
                    -ReplacedAssignment ($replacedDefinition -or $changedPolicyDefinitionId) `
                    -DeployedRoleAssignmentsByPrincipalId $deployedRoleAssignmentsByPrincipalId
                if ($identityStatus.requiresRoleChanges) {
                    $null = $RoleAssignments.added.AddRange($identityStatus.added)
                    $null = $RoleAssignments.updated.AddRange($identityStatus.updated)
                    $null = $RoleAssignments.removed.AddRange($identityStatus.removed)
                    $RoleAssignments.numberOfChanges += ($identityStatus.numberOfChanges)
                }
                if ($identityStatus.isUserAssigned) {
                    $isUserAssignedAny = $true
                }

                # Check if Policy assignment in Azure is the same as in the JSON file
                $changesStrings = @()
                $match = $displayNameMatches -and $descriptionMatches -and $parametersMatch -and $metadataMatches -and $definitionVersionMatches -and !$changePacOwnerId `
                    -and $enforcementModeMatches -and $notScopesMatch -and $nonComplianceMessagesMatches -and $overridesMatch -and $resourceSelectorsMatch -and !$identityStatus.replaced
                if ($match) {
                    # no Assignment properties changed
                    $Assignments.numberUnchanged++
                    if ($identityStatus.requiresRoleChanges) {
                        # role assignments for Managed Identity changed - caused by a mangedIdentityLocation changed or a previously failed role assignment failure
                        Write-AssignmentDetails -DisplayName $displayName -Scope $scope -Prefix "Update($($identityStatus.changedIdentityStrings -join ','))" -IdentityStatus $identityStatus
                    }
                    else {
                        # Write-AssignmentDetails -DisplayName $displayName -Scope $scope -Prefix "Unchanged" -IdentityStatus $identityStatus
                    }
                }
                else {
                    # One or more properties have changed
                    if ($identityStatus.replaced) {
                        # Assignment must be deleted and recreated (new)
                        if ($changedPolicyDefinitionId) {
                            $changesStrings += "definitionId"
                        }
                        if ($replacedDefinition) {
                            $changesStrings += "replacedDefinition"
                        }
                        $changesStrings += ($identityStatus.changedIdentityStrings)
                    }
                    elseif ($identityStatus.requiresRoleChanges) {
                        $changesStrings += ($identityStatus.changedIdentityStrings)
                    }

                    if (!$displayNameMatches) {
                        $changesStrings += "displayName"
                    }
                    if (!$descriptionMatches) {
                        $changesStrings += "description"
                    }
                    if ($changePacOwnerId) {
                        $changesStrings += "owner"
                    }
                    if (!$metadataMatches) {
                        $changesStrings += "metadata"
                    }
                    if (!$definitionVersionMatches) {
                        $changesStrings += "definitionVersion"
                    }
                    if (!$parametersMatch) {
                        $changesStrings += "parameters"
                    }
                    if (!$enforcementModeMatches) {
                        $changesStrings += "enforcementMode"
                    }
                    if (!$notScopesMatch) {
                        $changesStrings += "notScopes"
                    }
                    if (!$nonComplianceMessagesMatches) {
                        $changesStrings += "nonComplianceMessages"
                    }
                    if (!$overridesMatch) {
                        $changesStrings += "overrides"
                    }
                    if (!$resourceSelectorsMatch) {
                        $changesStrings += "resourceSelectors"
                    }

                    $changesString = $changesStrings -join ","
                    $updateCollection = $Assignments.update
                    $prefixText = "Update($changesString)"
                    if ($identityStatus.replaced) {
                        $prefixText = "Replace($changesString)"
                        $updateCollection = $Assignments.replace
                    }
                    if ($Assignments.update.ContainsKey($id) -or $Assignments.replace.ContainsKey($id)) {
                        Write-Error "Duplicate Policy Assignment ID '$id' found in the JSON files." -ErrorAction Stop
                    }
                    $null = $updateCollection.Add($id, $assignment)
                    Write-AssignmentDetails -DisplayName $displayName -Scope $scope -Prefix $prefixText -IdentityStatus $identityStatus
                    $Assignments.numberOfChanges++
                    if($ExtendedReporting){
                        # Define Changed Object Data for ExtendedReporting
                        # Populate Data Fields
                        Remove-Variable assignmentRecord -ErrorAction SilentlyContinue
                        $assignmentRecord = Get-DeepCloneAsOrderedHashtable -InputObject $fileRecord
                        $assignmentRecord.Set_Item('name', $name)
                        $assignmentRecord.Set_Item('id', $id)
                        $assignmentRecord.Set_Item('definitionType', 'assignment')
                        if ($changedPolicyDefinitionId) {
                            $assignmentRecord.Set_Item('changedPolicyDefinitionId', $changedPolicyDefinitionId)
                            $assignmentRecord.Set_Item('oldDefinitionId', $deployedPolicyAssignmentProperties.policyDefinitionId)
                            $assignmentRecord.Set_Item('newDefinitionId', $policyDefinitionId)
                            if ($(Split-Path $policyDefinitionId) -eq (Split-Path $deployedPolicyAssignmentProperties.policyDefinitionId)) {
                                $assignmentRecord.Set_Item('scopeChangedOnly', $true)
                            }
                            else {
                                $assignmentRecord.Set_Item('scopeChangedOnly', $false)
                            }
                        }
                        if ($replacedDefinition) {
                            $assignmentRecord.Set_Item('replacedReferencedDefinition', $replacedDefinition)
                            $assignmentRecord.Set_Item('newReferencedDefinition', $policyDefinitionId)
                            $assignmentRecord.Set_Item('oldReferencedDefinition', $deployedPolicyAssignmentProperties.policyDefinitionId)
                        }
                        if ($identityStatus.replaced -or $identityStatus.requiresRoleChanges) {
                            $assignmentRecord.Set_Item('requiresRoleChanges', $identityStatus.requiresRoleChanges)
                            $assignmentRecord.Set_Item('changedIdentityStrings', $identityStatus.changedIdentityStrings)
                            $assignmentRecord.Set_Item('roleAdded',$identityStatus.added)
                            $assignmentRecord.Set_Item('roleUpdated',$identityStatus.updated)
                            $assignmentRecord.Set_Item('roleRemoved',$identityStatus.removed)
                            $assignmentRecord.Set_Item('roleRReplaced',$identityStatus.replaced)
                        }
                        if (!$displayNameMatches) {
                            $assignmentRecord.Set_Item('displayNameChanged', (!($displayNameMatches)))
                            $assignmentRecord.Set_Item('newDisplayName', $displayName)
                            $assignmentRecord.Set_Item('oldDisplayName', $deployedPolicyAssignmentProperties.displayName)
                        }
                        if (!$descriptionMatches) {
                            $assignmentRecord.Set_Item('descriptionChanged', (!($descriptionMatches)))
                            $assignmentRecord.Set_Item('oldDescription', $deployedPolicyAssignmentProperties.description)
                            $assignmentRecord.Set_Item('newDescription', $description)
                        }
                        if ($changePacOwnerId) {
                            $assignmentRecord.Set_Item('ownerChanged', $changePacOwnerId)
                            $assignmentRecord.Set_Item('oldOwner', $deployedPolicyAssignmentProperties.metadata.pacOwnerId)
                            $assignmentRecord.Set_Item('newOwner', $metadata.pacOwnerId)
                        }              
                        if (!$descriptionMatches) {
                            $assignmentRecord.Set_Item('descriptionChanged', !($descriptionMatches))
                            $assignmentRecord.Set_Item('oldDescription', $deployedPolicyAssignmentProperties.description)
                            $assignmentRecord.Set_Item('newDescription', $description)
                        }
                        if (!$metadataMatches) {
                            $assignmentRecord.Set_Item('metadataChanged', !($metadataMatches))
                            $assignmentRecord.Set_Item('oldMetadata', $deployedPolicyAssignmentProperties.metadata)
                            $assignmentRecord.Set_Item('newMetadata', $metadata)
                        }          
                        if (!$definitionVersionMatches) {
                            $assignmentRecord.Set_Item('definitionVersionChanged', !($definitionVersionMatches))
                            $assignmentRecord.Set_Item('oldDefinitionVersion', $deployedPolicyAssignmentProperties.definitionVersion)
                            $assignmentRecord.Set_Item('newDefinitionVersion', $definitionVersion)
                        }
                        if (!$parametersMatch) {
                            $assignmentRecord.Set_Item('parametersChanged', !($parametersMatch))
                            $assignmentRecord.Set_Item('oldParameters', $deployedPolicyAssignmentProperties.parameters)
                            $assignmentRecord.Set_Item('newParameters', $parameters)
                        }
                        if (!$enforcementModeMatches) {
                            $assignmentRecord.Set_Item('enforcementModeChanged', !($enforcementModeMatches))
                            $assignmentRecord.Set_Item('oldEnforcementMode', $deployedPolicyAssignmentProperties.enforcementMode)
                            $assignmentRecord.Set_Item('newEnforcementMode', $enforcementMode)
                        }
                        if (!$notScopesMatch) {
                            $assignmentRecord.Set_Item('notScopesChanged', !($notScopesMatch))
                            $assignmentRecord.Set_Item('oldNotScopes', $deployedPolicyAssignmentProperties.notScopes)
                            $assignmentRecord.Set_Item('newNotScopes', $notScopes)
                        }
                        if (!$nonComplianceMessagesMatches) {
                            $assignmentRecord.Set_Item('nonComplianceMessagesChanged', !($nonComplianceMessagesMatches))
                            $assignmentRecord.Set_Item('oldNonComplianceMessages', $deployedPolicyAssignmentProperties.nonComplianceMessages)
                            $assignmentRecord.Set_Item('newNonComplianceMessages', $nonComplianceMessages)
                        }
                        if (!$overridesMatch) {
                            $assignmentRecord.Set_Item('overridesChanged', !($overridesMatch))
                            $assignmentRecord.Set_Item('oldOverrides', $deployedPolicyAssignmentProperties.overrides)
                            $assignmentRecord.Set_Item('newOverrides', $overrides)
                        }
                        if (!$resourceSelectorsMatch) {
                            $assignmentRecord.Set_Item('resourceSelectorsChanged', !($resourceSelectorsMatch))
                            $assignmentRecord.Set_Item('oldResourceSelectors', $deployedPolicyAssignmentProperties.resourceSelectors)
                            $assignmentRecord.Set_Item('newResourceSelectors', $resourceSelectors)
                        }
                        if ($changesString) {
                            $assignmentRecord.Set_Item('changes', $changesString)
                            $assignmentRecord.Set_Item('changeList', $changesStrings)
                        }
                        # Define update type
                        if($assignmentRecord.scopeChangedOnly -and $changedPolicyDefinitionId -and $changesStrings.count -eq 1){
                            $assignmentRecord.Set_Item('evaluationResult', 'DefinitionScopeUpdate')
                        }elseif($changesStrings.count -eq 1 -and $changePacOwnerId){
                            $assignmentRecord.Set_Item('evaluationResult', 'OnwerOnly')
                        }elseif($identityStatus.replaced -or $identityStatus.requiresRoleChanges){
                            # Confirm that RequiresRoleChanges and ParametersMatch trigger thism confirm
                            $assignmentRecord.Set_Item('evaluationResult', 'Replaced')
                        }
                        elseif($changesStrings.count -gt 0){
                            $assignmentRecord.Set_Item('evaluationResult', 'Update')
                        }
                    }
                }
            }
            else {
                # New Assignment
                $null = $Assignments.new.Add($id, $assignment)
                $Assignments.numberOfChanges++
                Remove-Variable identityStatus -ErrorAction SilentlyContinue
                $identityStatus = Build-AssignmentIdentityChanges `
                    -Existing $null `
                    -Assignment $assignment `
                    -ReplacedAssignment $false `
                    -DeployedRoleAssignmentsByPrincipalId $deployedRoleAssignmentsByPrincipalId
                if ($identityStatus.requiresRoleChanges) {
                    $null = $RoleAssignments.added.AddRange($identityStatus.added)
                    $RoleAssignments.numberOfChanges += ($identityStatus.numberOfChanges)
                }
                if ($identityStatus.isUserAssigned) {
                    $isUserAssignedAny = $true
                }
                if($ExtendedReporting){
                    # Add details to the NEW record
                    Remove-Variable assignmentRecord -ErrorAction SilentlyContinue
                    $assignmentRecord = Get-DeepCloneAsOrderedHashtable -InputObject $fileRecord
                    $assignmentRecord.Set_Item('name', $name)
                    $assignmentRecord.Set_Item('id', $id)
                    $assignmentRecord.Set_Item('evaluationResult', 'New')
                    $assignmentRecord.Set_Item('definitionType', 'assignment')
                    $assignmentRecord.Set_Item('changes', '*')
                    $assignmentRecord.Set_Item('changeList', @('*'))
                    $assignmentRecord.Set_Item('identityReplaced',"")
                    $assignmentRecord.Set_Item('replacedReferencedDefinition',"")
                    $assignmentRecord.Set_Item('displayNameChanged',"")
                    $assignmentRecord.Set_Item('descriptionChanged',"")
                    $assignmentRecord.Set_Item('definitionVersionChanged',"")
                    $assignmentRecord.Set_Item('parametersChanged',"")
                    $assignmentRecord.Set_Item('modeChanged',"")
                    $assignmentRecord.Set_Item('resourceSelectorsChanged',"")
                    $assignmentRecord.Set_Item('policyRuleChanged',"")
                    $assignmentRecord.Set_Item('replacedPolicy',"")
                    $assignmentRecord.Set_Item('policyDefinitionsChanged',"")
                    $assignmentRecord.Set_Item('policyDefinitionGroupsChanged',"")
                    $assignmentRecord.Set_Item('deletedPolicyDefinitionGroups',"")
                }
                Write-AssignmentDetails -DisplayName $displayName -Scope $scope -Prefix "New" -IdentityStatus $identityStatus
            }
            if($ExtendedReporting){
                try{
                    if(!$match){
                        $allAssignmentRecords.add($(@($assignmentRecord.fileRelativePath,$assignmentRecord.definitionType,$assignmentRecord.id) -join "_"),$assignmentRecord)
                    }
                    
                }catch{
                    Write-Host "Test"
                }                
            }
        }
    }

    $strategy = $PacEnvironment.desiredState.strategy
    $keepDfcSecurityAssignments = $PacEnvironment.desiredState.keepDfcSecurityAssignments
    if ($deleteCandidates.psbase.Count -gt 0) {
        foreach ($id in $deleteCandidates.Keys) {
            $deleteCandidate = $deleteCandidates.$id
            $deleteCandidateProperties = Get-PolicyResourceProperties $deleteCandidate
            $name = $deleteCandidate.name
            $displayName = $deleteCandidateProperties.displayName
            $scope = $deleteCandidateProperties.scope
            $pacOwner = $deleteCandidate.pacOwner
            $shallDelete = Confirm-DeleteForStrategy `
                -PacOwner $pacOwner `
                -Strategy $strategy `
                -KeepDfcSecurityAssignments $keepDfcSecurityAssignments
            if ($shallDelete) {
                # always delete if owned by this Policy as Code solution
                # never delete if owned by another Policy as Code solution
                # if strategy is "full", delete with unknown owner (missing pacOwnerId)
                Remove-Variable identityStatus -ErrorAction SilentlyContinue
                $identityStatus = Build-AssignmentIdentityChanges `
                    -Existing $deleteCandidate `
                    -Assignment $null `
                    -ReplacedAssignment $false `
                    -DeployedRoleAssignmentsByPrincipalId $deployedRoleAssignmentsByPrincipalId
                if ($identityStatus.requiresRoleChanges) {
                    $null = $RoleAssignments.removed.AddRange($identityStatus.removed)
                    $RoleAssignments.numberOfChanges += ($identityStatus.numberOfChanges)
                }
                if ($identityStatus.isUserAssigned) {
                    $isUserAssignedAny = $true
                }
                Write-AssignmentDetails -DisplayName $displayName -Scope $scope -Prefix "Delete" -IdentityStatus $identityStatus
                $splat = @{
                    id          = $id
                    name        = $name
                    scopeId     = $scope
                    displayName = $displayName
                }

                $AllAssignments.Remove($id)
                $Assignments.delete.Add($id, $splat)
                $Assignments.numberOfChanges++
                # Process Extended Reporting for items that are not part of the EPAC repository, but exist in the managed scope
                if($ExtendedReporting){
                    # Add record for any items that remain that will be deleted
                    Remove-Variable assignmentRecord -ErrorAction SilentlyContinue
                    $assignmentRecord = Get-DeepCloneAsOrderedHashtable -InputObject $DetailedRecord
                    $assignmentRecord.Set_Item('name', $name)
                    $assignmentRecord.Set_Item('id', $id)
                    $assignmentRecord.Set_Item('evaluationResult', 'Delete')
                    $assignmentRecord.Set_Item('fileRelativePath', "NoAssignmentFile")
                    $assignmentRecord.Set_Item('definitionType', 'assignment')
                }
            }
            else {
                $identityStatus = @{
                    requiresRoleChanges    = $false
                    numberOfChanges        = 0
                    added                  = @()
                    removed                = @()
                    changedIdentityStrings = @()
                    replaced               = $false
                    isUserAssigned         = $false
                }
                # Add record for any items that remain that will not be managed by EPAC

                $shortScope = $scope -replace "/providers/Microsoft.Management", ""
                switch ($pacOwner) {
                    thisPaC { 
                        Write-Error "Policy Assignment '$displayName' at $shortScope owned by this Policy as Code solution should have been deleted." -ErrorAction Stop
                        if($ExtendedReporting){
                            Remove-Variable assignmentRecord -ErrorAction SilentlyContinue
                            $assignmentRecord = Get-DeepCloneAsOrderedHashtable -InputObject $DetailedRecord
                            $assignmentRecord.Set_Item('name', $name)
                            $assignmentRecord.Set_Item('id', $id)
                            $assignmentRecord.Set_Item('evaluationResult', 'outOfScope-notFullDesiredState')
                            $assignmentRecord.Set_Item('fileRelativePath', "NoAssignmentFile")
                            $assignmentRecord.Set_Item('definitionType', 'assignment')
                            # $allAssignmentRecords.add($(@($assignmentRecord.fileRelativePath,$assignmentRecord.definitionType,$assignmentRecord.id) -join "_"),$assignmentRecord)
                        }
                    }
                    otherPaC {
                        if ($VerbosePreference -eq "Continue") {
                            Write-AssignmentDetails -DisplayName $displayName -Scope $shortScope -Prefix "Skipping delete (owned by other PaC):" -IdentityStatus $identityStatus
                        }
                        if($ExtendedReporting){
                            Remove-Variable assignmentRecord -ErrorAction SilentlyContinue
                            $assignmentRecord = Get-DeepCloneAsOrderedHashtable -InputObject $DetailedRecord
                            $assignmentRecord.Set_Item('name', $name)
                            $assignmentRecord.Set_Item('id', $id)
                            $assignmentRecord.Set_Item('evaluationResult', 'outOfScope-otherEpacManaged')
                            $assignmentRecord.Set_Item('fileRelativePath', "NoAssignmentFile")
                            $assignmentRecord.Set_Item('definitionType', 'assignment')
                            # $allAssignmentRecords.add($(@($assignmentRecord.fileRelativePath,$assignmentRecord.definitionType,$assignmentRecord.id) -join "_"),$assignmentRecord)
                        }
                    }
                    unknownOwner {
                        if ($VerbosePreference -eq "Continue") {
                            Write-AssignmentDetails -DisplayName $displayName -Scope $shortScope -Prefix "Skipping delete owned by unknown (strategy $strategy):" -IdentityStatus $identityStatus
                        }
                        if($ExtendedReporting){
                            Remove-Variable assignmentRecord -ErrorAction SilentlyContinue
                            $assignmentRecord = Get-DeepCloneAsOrderedHashtable -InputObject $DetailedRecord
                            $assignmentRecord.Set_Item('name', $name)
                            $assignmentRecord.Set_Item('id', $id)
                            $assignmentRecord.Set_Item('evaluationResult', 'outOfScope-notEpacManaged')
                            $assignmentRecord.Set_Item('fileRelativePath', "NoAssignmentFile")
                            $assignmentRecord.Set_Item('definitionType', 'assignment')
                            # $allAssignmentRecords.add($(@($assignmentRecord.fileRelativePath,$assignmentRecord.definitionType,$assignmentRecord.id) -join "_"),$assignmentRecord)
                        }
                    }
                    managedByDfcSecurityPolicies {
                        if ($VerbosePreference -eq "Continue") {
                            Write-AssignmentDetails -DisplayName $displayName -Scope $shortScope -Prefix "Skipping delete (DfC Security Policies):" -IdentityStatus $identityStatus
                        }
                        if($ExtendedReporting){
                            Remove-Variable assignmentRecord -ErrorAction SilentlyContinue
                            $assignmentRecord = Get-DeepCloneAsOrderedHashtable -InputObject $DetailedRecord
                            $assignmentRecord.Set_Item('name', $name)
                            $assignmentRecord.Set_Item('id', $id)
                            $assignmentRecord.Set_Item('evaluationResult', 'outOfScope-dfcManaged')
                            $assignmentRecord.Set_Item('fileRelativePath', "NoAssignmentFile")
                            $assignmentRecord.Set_Item('definitionType', 'assignment')
                            # $allAssignmentRecords.add($(@($assignmentRecord.fileRelativePath,$assignmentRecord.definitionType,$assignmentRecord.id) -join "_"),$assignmentRecord)
                        }
                    }
                    managedByDfcDefenderPlans {
                        if ($VerbosePreference -eq "Continue") {
                            Write-AssignmentDetails -DisplayName $displayName -Scope $shortScope -Prefix "Skipping delete (DfC Defender Plans):" -IdentityStatus $identityStatus
                        }
                        if($ExtendedReporting){
                            Remove-Variable assignmentRecord -ErrorAction SilentlyContinue
                            $assignmentRecord = Get-DeepCloneAsOrderedHashtable -InputObject $DetailedRecord
                            $assignmentRecord.Set_Item('name', $name)
                            $assignmentRecord.Set_Item('id', $id)
                            $assignmentRecord.Set_Item('evaluationResult', 'outOfScope-dfcManaged')
                            $assignmentRecord.Set_Item('fileRelativePath', "NoAssignmentFile")
                            $assignmentRecord.Set_Item('definitionType', 'assignment')
                            # $allAssignmentRecords.add($(@($assignmentRecord.fileRelativePath,$assignmentRecord.definitionType,$assignmentRecord.id) -join "_"),$assignmentRecord)
                        }
                    }
                }
            } 
            if($ExtendedReporting){
                $allAssignmentRecords.add($(@($assignmentRecord.fileRelativePath,$assignmentRecord.definitionType,$assignmentRecord.id) -join "_"),$assignmentRecord)
            }
        }
    }
    foreach($aRec in $allAssignmentRecords.keys){
        $detailedRecordList.Add($aRec,$allAssignmentRecords.$aRec)
    }
    if ($isUserAssignedAny) {
        Write-Warning "EPAC does not manage role assignments for Policy Assignments with user-assigned Managed Identities."
    }
    Write-Information "Number of unchanged Policy Assignments = $($Assignments.numberUnchanged)"
    Write-Information ""
}