Src/Private/Get-AbrIntuneConfigurationProfiles.ps1

function Get-AbrIntuneConfigurationProfiles {
    [CmdletBinding()]
    param ([Parameter(Position = 0, Mandatory)][string]$TenantId)

    begin {
        Write-PScriboMessage -Message "Collecting Intune Configuration Profiles for $TenantId."
        Show-AbrDebugExecutionTime -Start -TitleMessage 'Configuration Profiles'
    }

    process {
        Section -Style Heading2 'Configuration Profiles' {
            Paragraph "The following section documents the Device Configuration Profiles configured in tenant $TenantId."
            BlankLine

            $TotalConfigProfiles      = 0
            $UnassignedConfigProfiles = 0
            $TotalSettingsCatalog     = 0
            $TotalAdminTemplates      = 0
            $TotalSecurityBaselines   = if ($null -ne $script:TotalSecurityBaselines) { $script:TotalSecurityBaselines } else { 0 }

            #region Legacy Device Configuration Profiles
            try {
                Write-Host " - Retrieving device configuration profiles..."
                $ProfilesResp = Invoke-MgGraphRequest -Method GET `
                    -Uri "$($script:GraphEndpoint)/v1.0/deviceManagement/deviceConfigurations?`$expand=assignments" `
                    -ErrorAction Stop
                $Profiles = $ProfilesResp.value

                if ($Profiles -and @($Profiles).Count -gt 0) {
                    $null = ($TotalConfigProfiles = @($Profiles).Count)
                    Section -Style Heading3 'Device Configuration Profiles' {
                        BlankLine
                        $ProfObj = [System.Collections.ArrayList]::new()
                        foreach ($Profile in ($Profiles | Sort-Object displayName)) {
                            $OdataType = $Profile.'@odata.type' -replace '#microsoft.graph.', ''
                            $Platform  = switch -Wildcard ($OdataType) {
                                '*windows*' { 'Windows' } '*ios*'     { 'iOS / iPadOS' } '*android*' { 'Android' }
                                '*macOs*'   { 'macOS'   } '*edge*'    { 'Edge'          } default     { $OdataType }
                            }
                            $assignResolved = Resolve-IntuneAssignments -Assignments $Profile.assignments -CheckMemberCount:$script:CheckEmptyGroups
                            if ($assignResolved.AssignmentSummary -eq 'Not assigned') { $null = ($UnassignedConfigProfiles++) }
                            $scopeTagStr = if ($script:ResolveScopeTagNames -and $Profile.roleScopeTagIds) {
                                Get-IntuneScopeTagNames -ScopeTagIds $Profile.roleScopeTagIds
                            } else { 'Default' }
                            $ProfObj.Add([pscustomobject]([ordered]@{
                                'Profile Name'    = $Profile.displayName
                                'Platform'        = $Platform
                                'Profile Type'    = $OdataType
                                'Included Groups' = $assignResolved.IncludedGroups
                                'Excluded Groups' = $assignResolved.ExcludedGroups
                                'Scope Tags'      = $scopeTagStr
                                'Last Modified'   = if ($Profile.lastModifiedDateTime) { ([datetime]$Profile.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' }
                            })) | Out-Null
                        }
                        $null = (& { if ($HealthCheck.Intune.ConfigurationProfiles) { $null = ($ProfObj | Where-Object { $_.'Included Groups' -eq '--' } | Set-Style -Style Warning | Out-Null) } })
                        $ProfTableParams = @{ Name = "Device Configuration Profiles - $TenantId"; ColumnWidths = 20, 10, 18, 18, 14, 9, 11 }
                        if ($Report.ShowTableCaptions) { $ProfTableParams['Caption'] = "- $($ProfTableParams.Name)" }
                        $ProfObj | Table @ProfTableParams

                        if (Get-IntuneExcelSheetEnabled -SheetKey 'ConfigProfiles') { $script:ExcelSheets['Config Profiles'] = $ProfObj }
                        if (Get-IntuneBackupSectionEnabled -SectionKey 'ConfigurationProfiles') { $script:BackupData['ConfigurationProfiles'] = $Profiles }

                        #region InfoLevel 2 -- per-profile detail
                        if ($InfoLevel.ConfigurationProfiles -ge 2) {
                            foreach ($Profile in ($Profiles | Sort-Object displayName)) {
                                $OdataType = $Profile.'@odata.type' -replace '#microsoft.graph.', ''
                                $Platform  = switch -Wildcard ($OdataType) {
                                    '*windows*' { 'Windows' } '*ios*' { 'iOS / iPadOS' } '*android*' { 'Android' }
                                    '*macOs*'   { 'macOS'   } '*edge*'{ 'Edge'          } default    { $OdataType }
                                }
                                $assignResolved = Resolve-IntuneAssignments -Assignments $Profile.assignments

                                Section -Style Heading4 $Profile.displayName {
                                    BlankLine

                                    # --- Overview list table ---
                                    $overviewObj = [System.Collections.ArrayList]::new()
                                    $overviewObj.Add([pscustomobject]@{ Setting = 'Display Name';    Value = $Profile.displayName }) | Out-Null
                                    $overviewObj.Add([pscustomobject]@{ Setting = 'Platform';        Value = $Platform }) | Out-Null
                                    $overviewObj.Add([pscustomobject]@{ Setting = 'Profile Type';    Value = $OdataType }) | Out-Null
                                    $overviewObj.Add([pscustomobject]@{ Setting = 'Description';     Value = if ($Profile.description) { $Profile.description } else { '--' } }) | Out-Null
                                    $overviewObj.Add([pscustomobject]@{ Setting = 'Included Groups'; Value = $assignResolved.IncludedGroups }) | Out-Null
                                    $overviewObj.Add([pscustomobject]@{ Setting = 'Excluded Groups'; Value = $assignResolved.ExcludedGroups }) | Out-Null
                                    $overviewObj.Add([pscustomobject]@{ Setting = 'Scope Tags';      Value = if ($script:ResolveScopeTagNames -and $Profile.roleScopeTagIds) { Get-IntuneScopeTagNames -ScopeTagIds $Profile.roleScopeTagIds } else { 'Default' } }) | Out-Null
                                    $overviewObj.Add([pscustomobject]@{ Setting = 'Created';         Value = if ($Profile.createdDateTime) { ([datetime]$Profile.createdDateTime).ToString('yyyy-MM-dd') } else { '--' } }) | Out-Null
                                    $overviewObj.Add([pscustomobject]@{ Setting = 'Last Modified';   Value = if ($Profile.lastModifiedDateTime) { ([datetime]$Profile.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' } }) | Out-Null

                                    $OvTableParams = @{ Name = "Profile Overview - $($Profile.displayName)"; List = $true; ColumnWidths = 30, 70 }
                                    $overviewObj | Table @OvTableParams

                                    # --- Custom profile OMA-URI settings ---
                                    if ($Profile.omaSettings -and @($Profile.omaSettings).Count -gt 0) {
                                        BlankLine
                                        Paragraph "OMA-URI Settings ($(@($Profile.omaSettings).Count) setting(s)):"
                                        BlankLine
                                        $omaObj = [System.Collections.ArrayList]::new()
                                        foreach ($oma in $Profile.omaSettings) {
                                            $omaType = $oma.'@odata.type' -replace '#microsoft.graph.omaSettings', '' -replace 'OmaSetting', ''
                                            $omaValue = switch -Wildcard ($oma.'@odata.type') {
                                                '*Integer*'  { $oma.value }
                                                '*Boolean*'  { $oma.value }
                                                '*String*'   { if ($oma.value -and $oma.value.Length -gt 80) { "$($oma.value.Substring(0,80))..." } else { $oma.value } }
                                                '*Base64*'   { '[Base64 encoded data]' }
                                                '*FloatingPoint*' { $oma.value }
                                                '*DateTime*' { $oma.value }
                                                default      { if ($oma.value) { $oma.value } else { '--' } }
                                            }
                                            $omaObj.Add([pscustomobject]([ordered]@{
                                                'Setting Name' = $oma.displayName
                                                'OMA-URI'      = $oma.omaUri
                                                'Data Type'    = $omaType
                                                'Value'        = $omaValue
                                                'Description'  = if ($oma.description) { $oma.description } else { '--' }
                                            })) | Out-Null
                                        }
                                        $OmaTableParams = @{ Name = "OMA-URI Settings - $($Profile.displayName)"; ColumnWidths = 20, 28, 10, 22, 20 }
                                        if ($Report.ShowTableCaptions) { $OmaTableParams['Caption'] = "- $($OmaTableParams.Name)" }
                                        $omaObj | Table @OmaTableParams
                                    }

                                    # --- Key typed settings for non-custom profiles ---
                                    # Extract well-known top-level properties that are actual config values
                                    # (not system fields like id, createdDateTime, etc.)
                                    $systemFields = @('id','displayName','description','createdDateTime',
                                        'lastModifiedDateTime','version','roleScopeTagIds',
                                        'supportsScopeTags','assignments','@odata.type',
                                        'deviceManagementApplicabilityRuleOsEdition',
                                        'deviceManagementApplicabilityRuleOsVersion',
                                        'deviceManagementApplicabilityRuleDeviceMode')

                                    if (-not ($Profile.omaSettings -and @($Profile.omaSettings).Count -gt 0)) {
                                        $settingProps = $Profile.PSObject.Properties |
                                            Where-Object { $_.Name -notin $systemFields -and $null -ne $_.Value -and $_.Value -ne '' }

                                        if ($settingProps -and @($settingProps).Count -gt 0) {
                                            BlankLine
                                            Paragraph "Configuration Settings ($(@($settingProps).Count) property/properties configured):"
                                            BlankLine
                                            $settingsObj = [System.Collections.ArrayList]::new()
                                            foreach ($prop in ($settingProps | Sort-Object Name)) {
                                                $val = switch ($prop.Value.GetType().Name) {
                                                    'Boolean'  { if ($prop.Value) { 'Enabled' } else { 'Disabled' } }
                                                    'PSCustomObject' { ($prop.Value | ConvertTo-Json -Depth 3 -Compress) }
                                                    'Object[]' { ($prop.Value -join ', ') }
                                                    default    { "$($prop.Value)" }
                                                }
                                                if ($val.Length -gt 120) { $val = "$($val.Substring(0,120))..." }
                                                # Convert camelCase to readable label
                                                $label = $prop.Name -creplace '([A-Z])', ' $1' -replace '^\s+', '' -replace '\s+', ' '
                                                $settingsObj.Add([pscustomobject]([ordered]@{
                                                    'Setting' = $label
                                                    'Value'   = $val
                                                })) | Out-Null
                                            }
                                            $SetTableParams = @{ Name = "Settings - $($Profile.displayName)"; List = $true; ColumnWidths = 40, 60 }
                                            $settingsObj | Table @SetTableParams
                                        }
                                    }
                                } # end Section Heading4
                            } # end foreach Profile (InfoLevel 2)
                        }
                        #endregion InfoLevel 2
                    }
                }
            } catch { if (Test-AbrGraphForbidden -ErrorRecord $_) { Write-AbrPermissionError -Section 'Device Configuration Profiles' -RequiredRole 'Intune Service Administrator or Global Administrator' } else { Write-AbrSectionError -Section 'Device Configuration Profiles' -Message "$($_.Exception.Message)" } }
            #endregion

            #region Settings Catalog
            try {
                Write-Host " - Retrieving Settings Catalog policies..."
                $CatalogResp = Invoke-MgGraphRequest -Method GET `
                    -Uri "$($script:GraphEndpoint)/beta/deviceManagement/configurationPolicies?`$expand=assignments" `
                    -ErrorAction SilentlyContinue
                $CatalogPolicies = $CatalogResp.value
                if ($CatalogPolicies -and @($CatalogPolicies).Count -gt 0) {
                    $null = ($TotalSettingsCatalog = @($CatalogPolicies).Count)
                    Section -Style Heading3 'Settings Catalog Policies' {
                        BlankLine
                        $CatObj = [System.Collections.ArrayList]::new()
                        foreach ($CatPolicy in ($CatalogPolicies | Sort-Object name)) {
                            $Platform = switch ($CatPolicy.platforms) {
                                'windows10' { 'Windows 10/11' } 'macOS' { 'macOS' } 'iOS' { 'iOS / iPadOS' }
                                'android'   { 'Android'       } default { if ($CatPolicy.platforms) { $CatPolicy.platforms } else { '--' } }
                            }
                            $assignResolved = Resolve-IntuneAssignments -Assignments $CatPolicy.assignments -CheckMemberCount:$script:CheckEmptyGroups
                            if ($assignResolved.AssignmentSummary -eq 'Not assigned') { $null = ($UnassignedConfigProfiles++) }
                            $CatObj.Add([pscustomobject]([ordered]@{
                                'Policy Name'     = $CatPolicy.name
                                'Platform'        = $Platform
                                'Technology'      = if ($CatPolicy.technologies) { $CatPolicy.technologies } else { '--' }
                                'Included Groups' = $assignResolved.IncludedGroups
                                'Excluded Groups' = $assignResolved.ExcludedGroups
                                'Last Modified'   = if ($CatPolicy.lastModifiedDateTime) { ([datetime]$CatPolicy.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' }
                            })) | Out-Null
                        }
                        $null = (& { if ($HealthCheck.Intune.ConfigurationProfiles) { $null = ($CatObj | Where-Object { $_.'Included Groups' -eq '--' } | Set-Style -Style Warning | Out-Null) } })
                        $CatTableParams = @{ Name = "Settings Catalog Policies - $TenantId"; ColumnWidths = 22, 13, 15, 20, 18, 12 }
                        if ($Report.ShowTableCaptions) { $CatTableParams['Caption'] = "- $($CatTableParams.Name)" }
                        $CatObj | Table @CatTableParams
                        if (Get-IntuneExcelSheetEnabled -SheetKey 'SettingsCatalog') { $script:ExcelSheets['Settings Catalog'] = $CatObj }
                        if (Get-IntuneBackupSectionEnabled -SectionKey 'SettingsCatalog') { $script:BackupData['SettingsCatalog'] = $CatalogPolicies }

                        #region InfoLevel 2 -- Settings Catalog per-policy settings
                        if ($InfoLevel.ConfigurationProfiles -ge 2) {
                            foreach ($CatPolicy in ($CatalogPolicies | Sort-Object name)) {
                                $Platform = switch ($CatPolicy.platforms) {
                                    'windows10' { 'Windows 10/11' } 'macOS' { 'macOS' } 'iOS' { 'iOS / iPadOS' }
                                    'android'   { 'Android'       } default { if ($CatPolicy.platforms) { $CatPolicy.platforms } else { '--' } }
                                }
                                $assignResolved = Resolve-IntuneAssignments -Assignments $CatPolicy.assignments

                                Section -Style Heading4 $CatPolicy.name {
                                    BlankLine

                                    # Overview
                                    $ovObj = [System.Collections.ArrayList]::new()
                                    $ovObj.Add([pscustomobject]@{ Setting = 'Policy Name';      Value = $CatPolicy.name }) | Out-Null
                                    $ovObj.Add([pscustomobject]@{ Setting = 'Platform';         Value = $Platform }) | Out-Null
                                    $ovObj.Add([pscustomobject]@{ Setting = 'Technologies';     Value = if ($CatPolicy.technologies) { $CatPolicy.technologies } else { '--' } }) | Out-Null
                                    $ovObj.Add([pscustomobject]@{ Setting = 'Description';      Value = if ($CatPolicy.description) { $CatPolicy.description } else { '--' } }) | Out-Null
                                    $ovObj.Add([pscustomobject]@{ Setting = 'Included Groups';  Value = $assignResolved.IncludedGroups }) | Out-Null
                                    $ovObj.Add([pscustomobject]@{ Setting = 'Excluded Groups';  Value = $assignResolved.ExcludedGroups }) | Out-Null
                                    $ovObj.Add([pscustomobject]@{ Setting = 'Last Modified';    Value = if ($CatPolicy.lastModifiedDateTime) { ([datetime]$CatPolicy.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' } }) | Out-Null
                                    $OvTableParams = @{ Name = "Policy Overview - $($CatPolicy.name)"; List = $true; ColumnWidths = 30, 70 }
                                    $ovObj | Table @OvTableParams

                                    # Fetch individual settings via /settings endpoint
                                    try {
                                        $SettingsResp = Invoke-MgGraphRequest -Method GET `
                                            -Uri "$($script:GraphEndpoint)/beta/deviceManagement/configurationPolicies/$($CatPolicy.id)/settings?`$expand=settingDefinitions" `
                                            -ErrorAction SilentlyContinue
                                        $PolicySettings = $SettingsResp.value

                                        if ($PolicySettings -and @($PolicySettings).Count -gt 0) {
                                            BlankLine
                                            Paragraph "Configured Settings ($(@($PolicySettings).Count) setting(s)):"
                                            BlankLine
                                            $catSetObj = [System.Collections.ArrayList]::new()
                                            foreach ($setting in $PolicySettings) {
                                                $instance = $setting.settingInstance
                                                if (-not $instance) { continue }

                                                # Get setting definition display name
                                                $defName = if ($instance.settingDefinitionId) {
                                                    # Convert definition ID to readable name
                                                    $instance.settingDefinitionId -replace '^.*_', '' -replace '_', ' ' -replace '([a-z])([A-Z])', '$1 $2'
                                                } else { '--' }

                                                # Extract value based on instance type
                                                $settingValue = switch -Wildcard ($instance.'@odata.type') {
                                                    '*choiceSettingInstance' {
                                                        if ($instance.choiceSettingValue -and $instance.choiceSettingValue.value) {
                                                            $instance.choiceSettingValue.value -replace '^.*_', ''
                                                        } else { '--' }
                                                    }
                                                    '*simpleSettingInstance' {
                                                        if ($instance.simpleSettingValue) { "$($instance.simpleSettingValue.value)" } else { '--' }
                                                    }
                                                    '*simpleSettingCollectionInstance' {
                                                        if ($instance.simpleSettingCollectionValue) {
                                                            ($instance.simpleSettingCollectionValue | ForEach-Object { $_.value }) -join ', '
                                                        } else { '--' }
                                                    }
                                                    '*groupSettingCollectionInstance' { '[Group collection -- see JSON backup for full detail]' }
                                                    default { '--' }
                                                }
                                                if ($settingValue.Length -gt 100) { $settingValue = "$($settingValue.Substring(0,100))..." }

                                                $catSetObj.Add([pscustomobject]([ordered]@{
                                                    'Setting'           = $defName
                                                    'Definition ID'     = $instance.settingDefinitionId
                                                    'Value'             = $settingValue
                                                })) | Out-Null
                                            }
                                            $CatSetTableParams = @{ Name = "Settings - $($CatPolicy.name)"; ColumnWidths = 28, 42, 30 }
                                            if ($Report.ShowTableCaptions) { $CatSetTableParams['Caption'] = "- $($CatSetTableParams.Name)" }
                                            $catSetObj | Table @CatSetTableParams
                                        }
                                    } catch {
                                        Paragraph "Could not retrieve settings detail: $($_.Exception.Message)"
                                    }
                                } # end Heading4
                            } # end foreach CatPolicy
                        }
                        #endregion InfoLevel 2
                    }
                }
            } catch { if (Test-AbrGraphForbidden -ErrorRecord $_) { Write-AbrPermissionError -Section 'Settings Catalog Policies' -RequiredRole 'Intune Service Administrator or Global Administrator' } else { Write-AbrSectionError -Section 'Settings Catalog Policies' -Message "$($_.Exception.Message)" } }
            #endregion

            #region Administrative Templates
            try {
                Write-Host " - Retrieving Administrative Templates..."
                $GPResp = Invoke-MgGraphRequest -Method GET `
                    -Uri "$($script:GraphEndpoint)/beta/deviceManagement/groupPolicyConfigurations?`$expand=assignments" `
                    -ErrorAction SilentlyContinue
                $GPPolicies = $GPResp.value
                if ($GPPolicies -and @($GPPolicies).Count -gt 0) {
                    $null = ($TotalAdminTemplates = @($GPPolicies).Count)
                    Section -Style Heading3 'Administrative Templates' {
                        BlankLine
                        $GPObj = [System.Collections.ArrayList]::new()
                        foreach ($GPPolicy in ($GPPolicies | Sort-Object displayName)) {
                            $assignResolved = Resolve-IntuneAssignments -Assignments $GPPolicy.assignments -CheckMemberCount:$script:CheckEmptyGroups
                            if ($assignResolved.AssignmentSummary -eq 'Not assigned') { $null = ($UnassignedConfigProfiles++) }
                            $GPObj.Add([pscustomobject]([ordered]@{
                                'Policy Name'     = $GPPolicy.displayName
                                'Description'     = if ($GPPolicy.description) { $GPPolicy.description } else { '--' }
                                'Included Groups' = $assignResolved.IncludedGroups
                                'Excluded Groups' = $assignResolved.ExcludedGroups
                                'Last Modified'   = if ($GPPolicy.lastModifiedDateTime) { ([datetime]$GPPolicy.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' }
                            })) | Out-Null
                        }
                        $null = (& { if ($HealthCheck.Intune.ConfigurationProfiles) { $null = ($GPObj | Where-Object { $_.'Included Groups' -eq '--' } | Set-Style -Style Warning | Out-Null) } })
                        $GPTableParams = @{ Name = "Administrative Templates - $TenantId"; ColumnWidths = 24, 26, 22, 16, 12 }
                        if ($Report.ShowTableCaptions) { $GPTableParams['Caption'] = "- $($GPTableParams.Name)" }
                        $GPObj | Table @GPTableParams
                        if (Get-IntuneExcelSheetEnabled -SheetKey 'AdminTemplates') { $script:ExcelSheets['Admin Templates'] = $GPObj }
                        if (Get-IntuneBackupSectionEnabled -SectionKey 'AdminTemplates') { $script:BackupData['AdminTemplates'] = $GPPolicies }

                        #region InfoLevel 2 -- Admin Templates per-policy definition values
                        if ($InfoLevel.ConfigurationProfiles -ge 2) {
                            foreach ($GPPolicy in ($GPPolicies | Sort-Object displayName)) {
                                $assignResolved = Resolve-IntuneAssignments -Assignments $GPPolicy.assignments
                                Section -Style Heading4 $GPPolicy.displayName {
                                    BlankLine

                                    # Overview
                                    $gpOvObj = [System.Collections.ArrayList]::new()
                                    $gpOvObj.Add([pscustomobject]@{ Setting = 'Policy Name';     Value = $GPPolicy.displayName }) | Out-Null
                                    $gpOvObj.Add([pscustomobject]@{ Setting = 'Description';     Value = if ($GPPolicy.description) { $GPPolicy.description } else { '--' } }) | Out-Null
                                    $gpOvObj.Add([pscustomobject]@{ Setting = 'Included Groups'; Value = $assignResolved.IncludedGroups }) | Out-Null
                                    $gpOvObj.Add([pscustomobject]@{ Setting = 'Excluded Groups'; Value = $assignResolved.ExcludedGroups }) | Out-Null
                                    $gpOvObj.Add([pscustomobject]@{ Setting = 'Last Modified';   Value = if ($GPPolicy.lastModifiedDateTime) { ([datetime]$GPPolicy.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' } }) | Out-Null
                                    $GpOvTableParams = @{ Name = "Template Overview - $($GPPolicy.displayName)"; List = $true; ColumnWidths = 30, 70 }
                                    $gpOvObj | Table @GpOvTableParams

                                    # Fetch configured definition values
                                    try {
                                        $DefsResp = Invoke-MgGraphRequest -Method GET `
                                            -Uri "$($script:GraphEndpoint)/beta/deviceManagement/groupPolicyConfigurations/$($GPPolicy.id)/definitionValues?`$expand=definition" `
                                            -ErrorAction SilentlyContinue
                                        $DefinitionValues = $DefsResp.value

                                        if ($DefinitionValues -and @($DefinitionValues).Count -gt 0) {
                                            BlankLine
                                            Paragraph "Configured Definitions ($(@($DefinitionValues).Count) definition(s)):"
                                            BlankLine
                                            $gpDefObj = [System.Collections.ArrayList]::new()
                                            foreach ($defVal in ($DefinitionValues | Sort-Object { $_.definition.displayName })) {
                                                # Fetch presentation values for this definition
                                                $presValue = '--'
                                                try {
                                                    $PresResp = Invoke-MgGraphRequest -Method GET `
                                                        -Uri "$($script:GraphEndpoint)/beta/deviceManagement/groupPolicyConfigurations/$($GPPolicy.id)/definitionValues/$($defVal.id)/presentationValues?`$expand=presentation" `
                                                        -ErrorAction SilentlyContinue
                                                    if ($PresResp.value -and @($PresResp.value).Count -gt 0) {
                                                        $presValues = $PresResp.value | ForEach-Object {
                                                            $label = if ($_.presentation.label) { "$($_.presentation.label): " } else { '' }
                                                            $val   = if ($null -ne $_.value) { "$($_.value)" } else { 'Configured' }
                                                            "$label$val"
                                                        }
                                                        $presValue = $presValues -join '; '
                                                        if ($presValue.Length -gt 120) { $presValue = "$($presValue.Substring(0,120))..." }
                                                    }
                                                } catch { $presValue = 'See JSON backup' }

                                                $gpDefObj.Add([pscustomobject]([ordered]@{
                                                    'Setting Name' = if ($defVal.definition.displayName) { $defVal.definition.displayName } else { $defVal.id }
                                                    'Category'     = if ($defVal.definition.categoryPath) { $defVal.definition.categoryPath } else { '--' }
                                                    'State'        = if ($defVal.enabled) { 'Enabled' } else { 'Disabled' }
                                                    'Value'        = $presValue
                                                })) | Out-Null
                                            }
                                            $GpDefTableParams = @{ Name = "Definition Values - $($GPPolicy.displayName)"; ColumnWidths = 30, 26, 10, 34 }
                                            if ($Report.ShowTableCaptions) { $GpDefTableParams['Caption'] = "- $($GpDefTableParams.Name)" }
                                            $gpDefObj | Table @GpDefTableParams
                                        }
                                    } catch {
                                        Paragraph "Could not retrieve definition values: $($_.Exception.Message)"
                                    }
                                } # end Heading4
                            } # end foreach GPPolicy
                        }
                        #endregion InfoLevel 2
                    }
                }
            } catch { if (Test-AbrGraphForbidden -ErrorRecord $_) { Write-AbrPermissionError -Section 'Administrative Templates' -RequiredRole 'Intune Service Administrator or Global Administrator' } else { Write-AbrSectionError -Section 'Administrative Templates' -Message "$($_.Exception.Message)" } }
            #endregion

            $null = ($script:TotalConfigProfilesAll = $TotalConfigProfiles + $TotalSettingsCatalog + $TotalAdminTemplates)

            #region ACSC E8 Assessment
            if ($script:IncludeACSCe8) {
                BlankLine
                Paragraph "ACSC Essential Eight Maturity Level Assessment -- Configuration Profiles:"
                BlankLine
                try {
                    $_v = @{
                        TotalConfigProfiles      = $script:TotalConfigProfilesAll
                        UnassignedConfigProfiles = $UnassignedConfigProfiles
                        TotalSettingsCatalog     = $TotalSettingsCatalog
                        TotalAdminTemplates      = $TotalAdminTemplates
                        TotalSecurityBaselines   = $TotalSecurityBaselines
                    }
                    $E8Checks = Build-AbrIntuneComplianceChecks -Definitions (Get-AbrIntuneE8Checks -Section 'ConfigurationProfiles') -Framework E8 -CallerVariables $_v
                    New-AbrIntuneE8AssessmentTable -Checks $E8Checks -Name 'Configuration Profiles' -TenantId $TenantId
                    if ($E8Checks) { $null = $script:E8AllChecks.AddRange([object[]](@($E8Checks | Select-Object @{N='Section';E={'ConfigurationProfiles'}}, ML, Control, Status, Detail))) }
                } catch { if (Test-AbrGraphForbidden -ErrorRecord $_) { Write-AbrPermissionError -Section 'E8 Configuration Profiles Assessment' -RequiredRole 'Intune Service Administrator or Global Administrator' } else { Write-AbrSectionError -Section 'E8 Configuration Profiles Assessment' -Message "$($_.Exception.Message)" } }
            }
            #endregion

            #region CIS Assessment
            if ($script:IncludeCISBaseline) {
                BlankLine
                Paragraph "CIS Microsoft 365 Foundations Benchmark Assessment -- Configuration Profiles:"
                BlankLine
                try {
                    $_v = @{
                        TotalConfigProfiles      = $script:TotalConfigProfilesAll
                        UnassignedConfigProfiles = $UnassignedConfigProfiles
                        TotalSecurityBaselines   = $TotalSecurityBaselines
                    }
                    $CISChecks = Build-AbrIntuneComplianceChecks -Definitions (Get-AbrIntuneCISChecks -Section 'ConfigurationProfiles') -Framework CIS -CallerVariables $_v
                    New-AbrIntuneCISAssessmentTable -Checks $CISChecks -Name 'Configuration Profiles' -TenantId $TenantId
                    if ($CISChecks) { $null = $script:CISAllChecks.AddRange([object[]](@($CISChecks | Select-Object @{N='Section';E={'ConfigurationProfiles'}}, CISControl, Level, Status, Detail))) }
                } catch { if (Test-AbrGraphForbidden -ErrorRecord $_) { Write-AbrPermissionError -Section 'CIS Configuration Profiles Assessment' -RequiredRole 'Intune Service Administrator or Global Administrator' } else { Write-AbrSectionError -Section 'CIS Configuration Profiles Assessment' -Message "$($_.Exception.Message)" } }
            }
            #endregion
        }
    }

    end { Show-AbrDebugExecutionTime -End -TitleMessage 'Configuration Profiles' }
}