Private/IntuneAnomalies.ps1

# Intune Anomalies - Private helpers

function New-IntuneAnomaliesHTMLReport {
    param(
        [Parameter(Mandatory = $true)]
        [string]$TenantName,

        [Parameter(Mandatory = $false)]
        [array]$Report_ApplicationFailureReport,
        [Parameter(Mandatory = $false)]
        [array]$Report_DevicesWithMultipleUsers,
        [Parameter(Mandatory = $false)]
        [array]$Report_DevicesWithoutAutopilotHash,
        [Parameter(Mandatory = $false)]
        [array]$Report_InactiveDevices,
        [Parameter(Mandatory = $false)]
        [array]$Report_OperatingSystemEditionOverview,
        [Parameter(Mandatory = $false)]
        [array]$Report_NoncompliantDevices,
        [Parameter(Mandatory = $false)]
        [array]$Report_DisabledPrimaryUsers,
        [Parameter(Mandatory = $false)]
        [array]$Report_BitLockerStatus,
        [Parameter(Mandatory = $false)]
        [array]$Report_LapsStatus,
        [Parameter(Mandatory = $false)]
        [array]$Report_DeprecatedSettings,
        [Parameter(Mandatory = $false)]
        [string[]]$Notices,
        [Parameter(Mandatory = $false)]
        [string]$ExportPath
    )

    # Default ExportPath to current folder if not provided
    if (-not $ExportPath) {
        $safeTenantName = $TenantName -replace '[\\/:*?"<>|]', '_'
        $ExportPath = Join-Path (Get-Location).Path "$safeTenantName-IntuneAnomaliesReport.html"
    }

    # Calculate counts for dashboard statistics
    $Report_ApplicationFailureReport_Count = $Report_ApplicationFailureReport | Measure-Object | Select-Object -ExpandProperty Count
    $Report_DevicesWithMultipleUsers_Count = $Report_DevicesWithMultipleUsers | Measure-Object | Select-Object -ExpandProperty Count
    $Report_DevicesWithoutAutopilotHash_Count = $Report_DevicesWithoutAutopilotHash | Measure-Object | Select-Object -ExpandProperty Count
    $Report_InactiveDevices_Count = $Report_InactiveDevices | Measure-Object | Select-Object -ExpandProperty Count
    $Report_NoncompliantDevices_Count = ($Report_NoncompliantDevices | Select-Object -Property DeviceName -Unique | Measure-Object).Count
    $Report_OperatingSystemEditionOverview_Count = $Report_OperatingSystemEditionOverview | Measure-Object | Select-Object -ExpandProperty Count
    $Report_DisabledPrimaryUsers_Count = $Report_DisabledPrimaryUsers | Measure-Object | Select-Object -ExpandProperty Count
    $Report_BitLockerStatus_Count = $Report_BitLockerStatus | Measure-Object | Select-Object -ExpandProperty Count
    $Report_LapsStatus_Count = $Report_LapsStatus | Measure-Object | Select-Object -ExpandProperty Count
    $Report_DeprecatedSettings_Count = $Report_DeprecatedSettings | Measure-Object | Select-Object -ExpandProperty Count
    $Report_DeprecatedPolicies_Count = ($Report_DeprecatedSettings | Select-Object -ExpandProperty PolicyId -Unique | Measure-Object).Count

    # Get the current date and time for the report header
    $CurrentDate = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")

    # Generate table rows for all application failures
    $applicationFailureRows = ""
    foreach ($item in $Report_ApplicationFailureReport) {
        $applicationFailureRows += @"
        <tr>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Customer))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Application))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Platform))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Version))</td>
            <td>$($item.FailedDeviceCount)</td>
            <td>$($item.FailedDevicePercentage)%</td>
        </tr>
"@

    }

    # Generate table rows for devices with multiple users
    $multipleUsersRows = ""
    foreach ($item in $Report_DevicesWithMultipleUsers) {
        $multipleUsersRows += @"
        <tr>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Customer))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceName))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.PrimaryUser))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.EnrollmentProfile))</td>
            <td><span class="rk-badge rk-badge-warn">$($item.usersLoggedOnCount)</span></td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.usersLoggedOnIds))</td>
        </tr>
"@

    }

    # Generate table rows for devices not registered for Autopilot
    $noAutopilotHashRows = ""
    foreach ($item in $Report_DevicesWithoutAutopilotHash) {
        $noAutopilotHashRows += @"
        <tr>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Customer))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceName))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.PrimaryUser))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Serialnumber))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceManufacturer))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceModel))</td>
        </tr>
"@

    }

    # Generate table rows for inactive devices
    $inactiveDevicesRows = ""
    foreach ($item in $Report_InactiveDevices) {
        $inactiveDevicesRows += @"
        <tr>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Customer))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceName))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.PrimaryUser))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Serialnumber))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceManufacturer))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceModel))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.LastContact))</td>
        </tr>
"@

    }

    # Generate table rows for noncompliant devices
    $noncompliantDevicesRows = ""
    foreach ($item in $Report_NoncompliantDevices) {
        $statusBadge = '<span class="rk-badge rk-badge-error">Noncompliant</span>'

        $noncompliantDevicesRows += @"
        <tr>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Customer))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceName))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.PrimaryUser))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Serialnumber))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceManufacturer))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceModel))</td>
            <td>$statusBadge</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.NoncompliantBasedOn))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.NoncompliantAlert))</td>
        </tr>
"@

    }

    # Generate table rows for OS Edition Overview
    $osEditionOverviewRows = ""
    foreach ($item in $Report_OperatingSystemEditionOverview) {
        $osEditionOverviewRows += @"
        <tr>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Customer))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceName))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.PrimaryUser))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.OperatingSystemEdition))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.OSFriendlyname))</td>
        </tr>
"@

    }

    # Generate table rows for BitLocker key escrow anomalies
    $bitLockerStatusRows = ""
    foreach ($item in $Report_BitLockerStatus) {
        $sevClass = switch ($item.Severity) { 'Critical' { 'rk-badge-error' } 'Warning' { 'rk-badge-warn' } default { 'rk-badge' } }
        $bitLockerStatusRows += @"
        <tr>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Customer))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceName))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.PrimaryUser))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Serialnumber))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.IsEncrypted))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.AppliedPolicies))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.KeyEscrowed))</td>
            <td><span class="rk-badge $sevClass">$([System.Net.WebUtility]::HtmlEncode($item.Severity))</span></td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Status))</td>
        </tr>
"@

    }

    # Generate table rows for Windows LAPS backup anomalies
    $lapsStatusRows = ""
    foreach ($item in $Report_LapsStatus) {
        $sevClass = switch ($item.Severity) { 'Critical' { 'rk-badge-error' } 'Warning' { 'rk-badge-warn' } default { 'rk-badge' } }
        $lapsStatusRows += @"
        <tr>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Customer))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceName))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.PrimaryUser))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Serialnumber))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.OwnerType))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.AppliedPolicies))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.LastBackupDateTime))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.BackupAgeDays))</td>
            <td><span class="rk-badge $sevClass">$([System.Net.WebUtility]::HtmlEncode($item.Severity))</span></td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Status))</td>
        </tr>
"@

    }

    # Generate table rows for deprecated Settings Catalog settings.
    # Customer / ConfiguredValue / DetectionSource intentionally omitted - they're
    # either constant (Customer) or redundant with the Setting Definition ID for
    # the common choice-setting case where Value == DefId + "_<n>". The full
    # record still carries those fields for downstream consumers.
    $deprecatedSettingsRows = ""
    foreach ($item in $Report_DeprecatedSettings) {
        $deprecatedSettingsRows += @"
        <tr>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.PolicyName))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Platform))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.SettingDisplayName))</td>
            <td><code>$([System.Net.WebUtility]::HtmlEncode($item.SettingDefinitionId))</code></td>
        </tr>
"@

    }

    # Generate table rows for disabled primary users
    $disabledPrimaryUsersRows = ""
    foreach ($item in $Report_DisabledPrimaryUsers) {
        $disabledPrimaryUsersRows += @"
        <tr>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Customer))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceName))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.PrimaryUser))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.Serialnumber))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceManufacturer))</td>
            <td>$([System.Net.WebUtility]::HtmlEncode($item.DeviceModel))</td>
        </tr>
"@

    }

    # Build stat tiles HTML (8 cards, each with a unique color, 5-column grid)
    $statsCardsHtml = @"
            <div class="rk-stat-tile t-rust">
                <div class="rk-stat-eyebrow">APPLICATION FAILURES</div>
                <div class="rk-stat-number">$Report_ApplicationFailureReport_Count</div>
                <div class="rk-stat-caption">Failed app installations</div>
            </div>
            <div class="rk-stat-tile t-olive">
                <div class="rk-stat-eyebrow">MULTIPLE USERS</div>
                <div class="rk-stat-number">$Report_DevicesWithMultipleUsers_Count</div>
                <div class="rk-stat-caption">Non-shared devices</div>
            </div>
            <div class="rk-stat-tile t-rose">
                <div class="rk-stat-eyebrow">NOT IN AUTOPILOT</div>
                <div class="rk-stat-number">$Report_DevicesWithoutAutopilotHash_Count</div>
                <div class="rk-stat-caption">No hash or corporate identifier</div>
            </div>
            <div class="rk-stat-tile t-amber">
                <div class="rk-stat-eyebrow">INACTIVE DEVICES</div>
                <div class="rk-stat-number">$Report_InactiveDevices_Count</div>
                <div class="rk-stat-caption">90+ days inactive</div>
            </div>
            <div class="rk-stat-tile t-violet">
                <div class="rk-stat-eyebrow">NONCOMPLIANT</div>
                <div class="rk-stat-number">$Report_NoncompliantDevices_Count</div>
                <div class="rk-stat-caption">Unique noncompliant devices</div>
            </div>
            <div class="rk-stat-tile t-teal">
                <div class="rk-stat-eyebrow">OS EDITIONS</div>
                <div class="rk-stat-number">$Report_OperatingSystemEditionOverview_Count</div>
                <div class="rk-stat-caption">OS edition entries</div>
            </div>
            <div class="rk-stat-tile t-slate">
                <div class="rk-stat-eyebrow">DISABLED USERS</div>
                <div class="rk-stat-number">$Report_DisabledPrimaryUsers_Count</div>
                <div class="rk-stat-caption">Disabled primary users</div>
            </div>
            <div class="rk-stat-tile t-steel">
                <div class="rk-stat-eyebrow">BITLOCKER</div>
                <div class="rk-stat-number">$Report_BitLockerStatus_Count</div>
                <div class="rk-stat-caption">Encryption / escrow gaps</div>
            </div>
            <div class="rk-stat-tile t-indigo">
                <div class="rk-stat-eyebrow">LAPS BACKUP</div>
                <div class="rk-stat-number">$Report_LapsStatus_Count</div>
                <div class="rk-stat-caption">LAPS coverage gaps</div>
            </div>
            <div class="rk-stat-tile t-pink">
                <div class="rk-stat-eyebrow">DEPRECATED SETTINGS</div>
                <div class="rk-stat-number">$Report_DeprecatedSettings_Count</div>
                <div class="rk-stat-caption">Across $Report_DeprecatedPolicies_Count polic(ies)</div>
            </div>
"@


    $noticesHtml = ''
    if ($Notices) {
        $noticeItems = ($Notices | ForEach-Object { '<li>' + [System.Net.WebUtility]::HtmlEncode($_) + '</li>' }) -join ''
        $noticesHtml = "<div class=`"rk-tab-intro`"><strong>Notes from this run:</strong><ul>$noticeItems</ul></div>"
    }

    # Build body content HTML (tabs + panels + filter containers + tables + script)
    $bodyContentHtml = @"
    $noticesHtml
    <!-- Tab Navigation -->
    <div class="rk-tabs">
        <button class="rk-tab active" data-target="panel-app-failures">Application Failures</button>
        <button class="rk-tab" data-target="panel-multiple-users">Multiple Users</button>
        <button class="rk-tab" data-target="panel-no-autopilot">Not in Autopilot</button>
        <button class="rk-tab" data-target="panel-inactive-devices">Inactive Devices</button>
        <button class="rk-tab" data-target="panel-noncompliant">Noncompliant</button>
        <button class="rk-tab" data-target="panel-os-edition">OS Edition Overview</button>
        <button class="rk-tab" data-target="panel-disabled-users">Disabled Primary Users</button>
        <button class="rk-tab" data-target="panel-bitlocker-status">BitLocker</button>
        <button class="rk-tab" data-target="panel-laps-status">Windows LAPS</button>
        <button class="rk-tab" data-target="panel-deprecated-settings">Deprecated Settings</button>
    </div>

    <!-- Application Failures Panel -->
    <div id="panel-app-failures" class="rk-panel active">
        <div class="rk-tab-intro"><strong>What we check:</strong> Windows apps in Intune with at least one failed installation, taken from the Intune app install status report and sorted by number of failed devices.</div>
        <div class="rk-filter-bar">
            <span>Filters:</span>
            <select id="appFailuresCustomerFilter" class="form-select" style="max-width:180px;">
                <option value="">All Customers</option>
            </select>
            <select id="appFailuresAppFilter" class="form-select" style="max-width:180px;">
                <option value="">All Applications</option>
            </select>
            <select id="appFailuresPlatformFilter" class="form-select" style="max-width:180px;">
                <option value="">All Platforms</option>
            </select>
            <select id="appFailuresVersionFilter" class="form-select" style="max-width:180px;">
                <option value="">All Versions</option>
            </select>
            <select id="appFailuresPercentageFilter" class="form-select" style="max-width:180px;">
                <option value="">All Percentages</option>
                <option value="0-20">0-20%</option>
                <option value="20-40">20-40%</option>
                <option value="40-60">40-60%</option>
                <option value="60-80">60-80%</option>
                <option value="80-100">80-100%</option>
            </select>
            <button class="rk-filter-chip" onclick="clearAppFailuresFilters()">Clear</button>
        </div>
        <div class="rk-card">
            <div class="rk-card-header">
                <span>Application Failures</span>
                <div class="rk-show-all">
                    <label class="rk-toggle-switch">
                        <input type="checkbox" id="appFailuresShowAllToggle">
                        <span class="rk-toggle-slider"></span>
                    </label>
                    <span>Show all</span>
                </div>
            </div>
            <div class="rk-card-body">
                <table id="appFailuresTable" class="table table-bordered" style="width:100%">
                    <thead>
                        <tr>
                            <th>Customer</th>
                            <th>Application</th>
                            <th>Platform</th>
                            <th>Version</th>
                            <th>Failed Device Count</th>
                            <th>Failed Device Percentage</th>
                        </tr>
                    </thead>
                    <tbody>
                        $applicationFailureRows
                    </tbody>
                </table>
            </div>
        </div>
    </div>

    <!-- Multiple Users Panel -->
    <div id="panel-multiple-users" class="rk-panel">
        <div class="rk-tab-intro"><strong>What we check:</strong> Devices enrolled with a user-driven (single-user) Autopilot profile where more than one user has signed in. These devices are meant for one person. Multiple users usually means the device was handed over without a reset, or that it is really used as a shared device, in which case a shared-device (self-deploying) enrollment is a better fit.</div>
        <div class="rk-filter-bar">
            <span>Filters:</span>
            <select id="multipleUsersCustomerFilter" class="form-select" style="max-width:180px;">
                <option value="">All Customers</option>
            </select>
            <select id="multipleUsersDeviceFilter" class="form-select" style="max-width:180px;">
                <option value="">All Devices</option>
            </select>
            <select id="multipleUsersPrimaryUserFilter" class="form-select" style="max-width:180px;">
                <option value="">All Users</option>
            </select>
            <select id="multipleUsersProfileFilter" class="form-select" style="max-width:180px;">
                <option value="">All Profiles</option>
            </select>
            <select id="multipleUsersCountFilter" class="form-select" style="max-width:180px;">
                <option value="">All Counts</option>
                <option value="2">2 Users</option>
                <option value="3">3 Users</option>
                <option value="4+">4+ Users</option>
            </select>
            <button class="rk-filter-chip" onclick="clearMultipleUsersFilters()">Clear</button>
        </div>
        <div class="rk-card">
            <div class="rk-card-header">
                <span>Devices with Multiple Users</span>
                <div class="rk-show-all">
                    <label class="rk-toggle-switch">
                        <input type="checkbox" id="multipleUsersShowAllToggle">
                        <span class="rk-toggle-slider"></span>
                    </label>
                    <span>Show all</span>
                </div>
            </div>
            <div class="rk-card-body">
                <table id="multipleUsersTable" class="table table-bordered" style="width:100%">
                    <thead>
                        <tr>
                            <th>Customer</th>
                            <th>Device Name</th>
                            <th>Primary User</th>
                            <th>Enrollment Profile</th>
                            <th>User Count</th>
                            <th>Logged On User IDs</th>
                        </tr>
                    </thead>
                    <tbody>
                        $multipleUsersRows
                    </tbody>
                </table>
            </div>
        </div>
    </div>

    <!-- Not in Autopilot Panel -->
    <div id="panel-no-autopilot" class="rk-panel">
        <div class="rk-tab-intro"><strong>What we check:</strong> Windows devices that are not registered for Autopilot at all: no hardware hash (Autopilot) and no corporate identifier (Autopilot device preparation). Cloud PCs and Dev Boxes are left out.</div>
        <div class="rk-filter-bar">
            <span>Filters:</span>
            <select id="noAutopilotCustomerFilter" class="form-select" style="max-width:180px;">
                <option value="">All Customers</option>
            </select>
            <select id="noAutopilotDeviceFilter" class="form-select" style="max-width:180px;">
                <option value="">All Devices</option>
            </select>
            <select id="noAutopilotUserFilter" class="form-select" style="max-width:180px;">
                <option value="">All Users</option>
            </select>
            <select id="noAutopilotManufacturerFilter" class="form-select" style="max-width:180px;">
                <option value="">All Manufacturers</option>
            </select>
            <select id="noAutopilotModelFilter" class="form-select" style="max-width:180px;">
                <option value="">All Models</option>
            </select>
            <button class="rk-filter-chip" onclick="clearNoAutopilotFilters()">Clear</button>
        </div>
        <div class="rk-card">
            <div class="rk-card-header">
                <span>Devices not registered for Autopilot</span>
                <div class="rk-show-all">
                    <label class="rk-toggle-switch">
                        <input type="checkbox" id="noAutopilotShowAllToggle">
                        <span class="rk-toggle-slider"></span>
                    </label>
                    <span>Show all</span>
                </div>
            </div>
            <div class="rk-card-body">
                <table id="noAutopilotTable" class="table table-bordered" style="width:100%">
                    <thead>
                        <tr>
                            <th>Customer</th>
                            <th>Device Name</th>
                            <th>Primary User</th>
                            <th>Serial Number</th>
                            <th>Manufacturer</th>
                            <th>Model</th>
                        </tr>
                    </thead>
                    <tbody>
                        $noAutopilotHashRows
                    </tbody>
                </table>
            </div>
        </div>
    </div>

    <!-- Inactive Devices Panel -->
    <div id="panel-inactive-devices" class="rk-panel">
        <div class="rk-tab-intro"><strong>What we check:</strong> Devices that have not synced with Intune in the last 90 days.</div>
        <div class="rk-filter-bar">
            <span>Filters:</span>
            <select id="inactiveCustomerFilter" class="form-select" style="max-width:180px;">
                <option value="">All Customers</option>
            </select>
            <select id="inactiveDeviceFilter" class="form-select" style="max-width:180px;">
                <option value="">All Devices</option>
            </select>
            <select id="inactiveUserFilter" class="form-select" style="max-width:180px;">
                <option value="">All Users</option>
            </select>
            <select id="inactiveManufacturerFilter" class="form-select" style="max-width:180px;">
                <option value="">All Manufacturers</option>
            </select>
            <select id="inactiveModelFilter" class="form-select" style="max-width:180px;">
                <option value="">All Models</option>
            </select>
            <select id="inactiveInactivityFilter" class="form-select" style="max-width:180px;">
                <option value="">All Periods</option>
                <option value="90-180">90-180 days</option>
                <option value="180+">180+ days</option>
            </select>
            <button class="rk-filter-chip" onclick="clearInactiveFilters()">Clear</button>
        </div>
        <div class="rk-card">
            <div class="rk-card-header">
                <span>Inactive Devices (90+ days)</span>
                <div class="rk-show-all">
                    <label class="rk-toggle-switch">
                        <input type="checkbox" id="inactiveDevicesShowAllToggle">
                        <span class="rk-toggle-slider"></span>
                    </label>
                    <span>Show all</span>
                </div>
            </div>
            <div class="rk-card-body">
                <table id="inactiveDevicesTable" class="table table-bordered" style="width:100%">
                    <thead>
                        <tr>
                            <th>Customer</th>
                            <th>Device Name</th>
                            <th>Primary User</th>
                            <th>Serial Number</th>
                            <th>Manufacturer</th>
                            <th>Model</th>
                            <th>Last Contact</th>
                        </tr>
                    </thead>
                    <tbody>
                        $inactiveDevicesRows
                    </tbody>
                </table>
            </div>
        </div>
    </div>

    <!-- Noncompliant Devices Panel -->
    <div id="panel-noncompliant" class="rk-panel">
        <div class="rk-tab-intro"><strong>What we check:</strong> Devices that Intune marks as noncompliant, with one row per compliance rule that failed. The Noncompliant Alert column leaves out the <em>device has not checked in</em> and <em>no compliance policy assigned</em> rules.</div>
        <div class="rk-filter-bar">
            <span>Filters:</span>
            <select id="noncompliantCustomerFilter" class="form-select" style="max-width:180px;">
                <option value="">All Customers</option>
            </select>
            <select id="noncompliantDeviceFilter" class="form-select" style="max-width:180px;">
                <option value="">All Devices</option>
            </select>
            <select id="noncompliantUserFilter" class="form-select" style="max-width:180px;">
                <option value="">All Users</option>
            </select>
            <select id="noncompliantManufacturerFilter" class="form-select" style="max-width:180px;">
                <option value="">All Manufacturers</option>
            </select>
            <select id="noncompliantModelFilter" class="form-select" style="max-width:180px;">
                <option value="">All Models</option>
            </select>
            <select id="noncompliantReasonFilter" class="form-select" style="max-width:180px;">
                <option value="">All Reasons</option>
            </select>
            <button class="rk-filter-chip" onclick="clearNoncompliantFilters()">Clear</button>
        </div>
        <div class="rk-card">
            <div class="rk-card-header">
                <span>Noncompliant Devices</span>
                <div class="rk-show-all">
                    <label class="rk-toggle-switch">
                        <input type="checkbox" id="noncompliantShowAllToggle">
                        <span class="rk-toggle-slider"></span>
                    </label>
                    <span>Show all</span>
                </div>
            </div>
            <div class="rk-card-body">
                <table id="noncompliantTable" class="table table-bordered" style="width:100%">
                    <thead>
                        <tr>
                            <th>Customer</th>
                            <th>Device Name</th>
                            <th>Primary User</th>
                            <th>Serial Number</th>
                            <th>Manufacturer</th>
                            <th>Model</th>
                            <th>Compliance Status</th>
                            <th>Noncompliant Based On</th>
                            <th>Noncompliant Alert</th>
                        </tr>
                    </thead>
                    <tbody>
                        $noncompliantDevicesRows
                    </tbody>
                </table>
            </div>
        </div>
    </div>

    <!-- OS Edition Overview Panel -->
    <div id="panel-os-edition" class="rk-panel">
        <div class="rk-tab-intro"><strong>What we check:</strong> Overview of every Windows device with its OS edition and Windows version. Use it to spot unexpected editions: a device running Pro where you expect Enterprise cannot use Enterprise-only features such as Credential Guard, so policies that rely on them silently do nothing.</div>
        <div class="rk-filter-bar">
            <span>Filters:</span>
            <select id="osEditionCustomerFilter" class="form-select" style="max-width:180px;">
                <option value="">All Customers</option>
            </select>
            <select id="osEditionDeviceFilter" class="form-select" style="max-width:180px;">
                <option value="">All Devices</option>
            </select>
            <select id="osEditionUserFilter" class="form-select" style="max-width:180px;">
                <option value="">All Users</option>
            </select>
            <select id="osEditionEditionFilter" class="form-select" style="max-width:180px;">
                <option value="">All Editions</option>
            </select>
            <select id="osEditionFriendlyNameFilter" class="form-select" style="max-width:180px;">
                <option value="">All OS Versions</option>
            </select>
            <button class="rk-filter-chip" onclick="clearOSEditionFilters()">Clear</button>
        </div>
        <div class="rk-card">
            <div class="rk-card-header">
                <span>Operating System Edition Overview</span>
                <div class="rk-show-all">
                    <label class="rk-toggle-switch">
                        <input type="checkbox" id="osEditionShowAllToggle">
                        <span class="rk-toggle-slider"></span>
                    </label>
                    <span>Show all</span>
                </div>
            </div>
            <div class="rk-card-body">
                <table id="osEditionTable" class="table table-bordered" style="width:100%">
                    <thead>
                        <tr>
                            <th>Customer</th>
                            <th>Device Name</th>
                            <th>Primary User</th>
                            <th>Operating System Edition</th>
                            <th>OS Friendly Name</th>
                        </tr>
                    </thead>
                    <tbody>
                        $osEditionOverviewRows
                    </tbody>
                </table>
            </div>
        </div>
    </div>

    <!-- Disabled Primary Users Panel -->
    <div id="panel-disabled-users" class="rk-panel">
        <div class="rk-tab-intro"><strong>What we check:</strong> Devices whose primary user has a disabled account in Entra ID.</div>
        <div class="rk-filter-bar">
            <span>Filters:</span>
            <select id="disabledUsersCustomerFilter" class="form-select" style="max-width:180px;">
                <option value="">All Customers</option>
            </select>
            <select id="disabledUsersDeviceFilter" class="form-select" style="max-width:180px;">
                <option value="">All Devices</option>
            </select>
            <select id="disabledUsersUserFilter" class="form-select" style="max-width:180px;">
                <option value="">All Users</option>
            </select>
            <select id="disabledUsersManufacturerFilter" class="form-select" style="max-width:180px;">
                <option value="">All Manufacturers</option>
            </select>
            <select id="disabledUsersModelFilter" class="form-select" style="max-width:180px;">
                <option value="">All Models</option>
            </select>
            <button class="rk-filter-chip" onclick="clearDisabledUsersFilters()">Clear</button>
        </div>
        <div class="rk-card">
            <div class="rk-card-header">
                <span>Devices with Disabled Primary Users</span>
                <div class="rk-show-all">
                    <label class="rk-toggle-switch">
                        <input type="checkbox" id="disabledUsersShowAllToggle">
                        <span class="rk-toggle-slider"></span>
                    </label>
                    <span>Show all</span>
                </div>
            </div>
            <div class="rk-card-body">
                <table id="disabledUsersTable" class="table table-bordered" style="width:100%">
                    <thead>
                        <tr>
                            <th>Customer</th>
                            <th>Device Name</th>
                            <th>Primary User</th>
                            <th>Serial Number</th>
                            <th>Manufacturer</th>
                            <th>Model</th>
                        </tr>
                    </thead>
                    <tbody>
                        $disabledPrimaryUsersRows
                    </tbody>
                </table>
            </div>
        </div>
    </div>

    <!-- BitLocker Panel -->
    <div id="panel-bitlocker-status" class="rk-panel">
        <div class="rk-tab-intro"><strong>What we check:</strong> Windows devices that are not encrypted, have no BitLocker policy assigned, or are encrypted without an OS-volume recovery key stored in Entra ID. Cloud PCs and Dev Boxes are left out. Devices deliberately excluded from BitLocker policies are hidden unless the report runs with <code>-ShowExcludedDevices</code>.</div>
        <div class="rk-filter-bar">
            <span>Filters:</span>
            <select id="bitLockerCustomerFilter" class="form-select" style="max-width:180px;">
                <option value="">All Customers</option>
            </select>
            <select id="bitLockerDeviceFilter" class="form-select" style="max-width:180px;">
                <option value="">All Devices</option>
            </select>
            <select id="bitLockerUserFilter" class="form-select" style="max-width:180px;">
                <option value="">All Users</option>
            </select>
            <select id="bitLockerKeyEscrowedFilter" class="form-select" style="max-width:180px;">
                <option value="">Any Key State</option>
            </select>
            <select id="bitLockerSeverityFilter" class="form-select" style="max-width:180px;">
                <option value="">All Severities</option>
            </select>
            <button class="rk-filter-chip" onclick="clearBitLockerFilters()">Clear</button>
        </div>
        <div class="rk-card">
            <div class="rk-card-header">
                <span>BitLocker Anomalies</span>
                <div class="rk-show-all">
                    <label class="rk-toggle-switch">
                        <input type="checkbox" id="bitLockerShowAllToggle">
                        <span class="rk-toggle-slider"></span>
                    </label>
                    <span>Show all</span>
                </div>
            </div>
            <div class="rk-card-body">
                <table id="bitLockerTable" class="table table-bordered" style="width:100%">
                    <thead>
                        <tr>
                            <th>Customer</th>
                            <th>Device Name</th>
                            <th>Primary User</th>
                            <th>Serial Number</th>
                            <th>Encrypted</th>
                            <th>Applied Policies</th>
                            <th>Key Escrowed</th>
                            <th>Severity</th>
                            <th>Status</th>
                        </tr>
                    </thead>
                    <tbody>
                        $bitLockerStatusRows
                    </tbody>
                </table>
            </div>
        </div>
    </div>

    <!-- Windows LAPS Panel -->
    <div id="panel-laps-status" class="rk-panel">
        <div class="rk-tab-intro"><strong>What we check:</strong> Windows devices without an Entra-backed Windows LAPS policy, with a LAPS policy but no password backed up to Entra ID, or with a backup older than 60 days. Devices deliberately excluded from LAPS policies are hidden unless the report runs with <code>-ShowExcludedDevices</code>.</div>
        <div class="rk-filter-bar">
            <span>Filters:</span>
            <select id="lapsCustomerFilter" class="form-select" style="max-width:180px;">
                <option value="">All Customers</option>
            </select>
            <select id="lapsDeviceFilter" class="form-select" style="max-width:180px;">
                <option value="">All Devices</option>
            </select>
            <select id="lapsUserFilter" class="form-select" style="max-width:180px;">
                <option value="">All Users</option>
            </select>
            <select id="lapsOwnerFilter" class="form-select" style="max-width:180px;">
                <option value="">All Ownerships</option>
            </select>
            <select id="lapsSeverityFilter" class="form-select" style="max-width:180px;">
                <option value="">All Severities</option>
            </select>
            <button class="rk-filter-chip" onclick="clearLapsFilters()">Clear</button>
        </div>
        <div class="rk-card">
            <div class="rk-card-header">
                <span>Windows LAPS Backup Anomalies</span>
                <div class="rk-show-all">
                    <label class="rk-toggle-switch">
                        <input type="checkbox" id="lapsShowAllToggle">
                        <span class="rk-toggle-slider"></span>
                    </label>
                    <span>Show all</span>
                </div>
            </div>
            <div class="rk-card-body">
                <table id="lapsTable" class="table table-bordered" style="width:100%">
                    <thead>
                        <tr>
                            <th>Customer</th>
                            <th>Device Name</th>
                            <th>Primary User</th>
                            <th>Serial Number</th>
                            <th>Ownership</th>
                            <th>Applied Policies</th>
                            <th>Last Backup</th>
                            <th>Backup Age (days)</th>
                            <th>Severity</th>
                            <th>Status</th>
                        </tr>
                    </thead>
                    <tbody>
                        $lapsStatusRows
                    </tbody>
                </table>
            </div>
        </div>
    </div>

    <!-- Deprecated Settings Panel -->
    <div id="panel-deprecated-settings" class="rk-panel">
        <div class="rk-tab-intro"><strong>What we check:</strong> Settings in your Settings Catalog policies that Microsoft has marked as deprecated. These may stop working or be removed in a future Intune release.</div>
        <div class="rk-filter-bar">
            <span>Filters:</span>
            <select id="deprecatedPlatformFilter" class="form-select" style="max-width:180px;">
                <option value="">All Platforms</option>
            </select>
            <button class="rk-filter-chip" onclick="clearDeprecatedFilters()">Clear</button>
        </div>
        <div class="rk-card">
            <div class="rk-card-header">
                <span>Deprecated Intune Settings</span>
                <div class="rk-show-all">
                    <label class="rk-toggle-switch">
                        <input type="checkbox" id="deprecatedShowAllToggle">
                        <span class="rk-toggle-slider"></span>
                    </label>
                    <span>Show all</span>
                </div>
            </div>
            <div class="rk-card-body">
                <table id="deprecatedTable" class="table table-bordered">
                    <thead>
                        <tr>
                            <th>Policy Name</th>
                            <th>Platform</th>
                            <th>Setting Display Name</th>
                            <th>Setting Definition ID</th>
                        </tr>
                    </thead>
                    <tbody>
                        $deprecatedSettingsRows
                    </tbody>
                </table>
            </div>
        </div>
    </div>

    <script>
    `$(document).ready(function() {
        // Initialize all tables using the shared helper
        var appFailuresTable = initRKTable('#appFailuresTable');
        var multipleUsersTable = initRKTable('#multipleUsersTable', { order: [[4, 'desc']] });
        var noAutopilotTable = initRKTable('#noAutopilotTable');
        var inactiveDevicesTable = initRKTable('#inactiveDevicesTable', { order: [[6, 'asc']] });
        var noncompliantTable = initRKTable('#noncompliantTable');
        var osEditionTable = initRKTable('#osEditionTable');
        var disabledUsersTable = initRKTable('#disabledUsersTable');
        var bitLockerTable = initRKTable('#bitLockerTable');
        var lapsTable = initRKTable('#lapsTable');
        var deprecatedTable = initRKTable('#deprecatedTable');

        // Populate filter dropdowns
        function populateFilters() {
            populateSelectFromColumn('appFailuresCustomerFilter', appFailuresTable, 0);
            populateSelectFromColumn('appFailuresAppFilter', appFailuresTable, 1);
            populateSelectFromColumn('appFailuresPlatformFilter', appFailuresTable, 2);
            populateSelectFromColumn('appFailuresVersionFilter', appFailuresTable, 3);

            populateSelectFromColumn('multipleUsersCustomerFilter', multipleUsersTable, 0);
            populateSelectFromColumn('multipleUsersDeviceFilter', multipleUsersTable, 1);
            populateSelectFromColumn('multipleUsersPrimaryUserFilter', multipleUsersTable, 2);
            populateSelectFromColumn('multipleUsersProfileFilter', multipleUsersTable, 3);

            populateSelectFromColumn('noAutopilotCustomerFilter', noAutopilotTable, 0);
            populateSelectFromColumn('noAutopilotDeviceFilter', noAutopilotTable, 1);
            populateSelectFromColumn('noAutopilotUserFilter', noAutopilotTable, 2);
            populateSelectFromColumn('noAutopilotManufacturerFilter', noAutopilotTable, 4);
            populateSelectFromColumn('noAutopilotModelFilter', noAutopilotTable, 5);

            populateSelectFromColumn('inactiveCustomerFilter', inactiveDevicesTable, 0);
            populateSelectFromColumn('inactiveDeviceFilter', inactiveDevicesTable, 1);
            populateSelectFromColumn('inactiveUserFilter', inactiveDevicesTable, 2);
            populateSelectFromColumn('inactiveManufacturerFilter', inactiveDevicesTable, 4);
            populateSelectFromColumn('inactiveModelFilter', inactiveDevicesTable, 5);

            populateSelectFromColumn('noncompliantCustomerFilter', noncompliantTable, 0);
            populateSelectFromColumn('noncompliantDeviceFilter', noncompliantTable, 1);
            populateSelectFromColumn('noncompliantUserFilter', noncompliantTable, 2);
            populateSelectFromColumn('noncompliantManufacturerFilter', noncompliantTable, 4);
            populateSelectFromColumn('noncompliantModelFilter', noncompliantTable, 5);
            populateSelectFromColumn('noncompliantReasonFilter', noncompliantTable, 7);

            populateSelectFromColumn('osEditionCustomerFilter', osEditionTable, 0);
            populateSelectFromColumn('osEditionDeviceFilter', osEditionTable, 1);
            populateSelectFromColumn('osEditionUserFilter', osEditionTable, 2);
            populateSelectFromColumn('osEditionEditionFilter', osEditionTable, 3);
            populateSelectFromColumn('osEditionFriendlyNameFilter', osEditionTable, 4);

            populateSelectFromColumn('disabledUsersCustomerFilter', disabledUsersTable, 0);
            populateSelectFromColumn('disabledUsersDeviceFilter', disabledUsersTable, 1);
            populateSelectFromColumn('disabledUsersUserFilter', disabledUsersTable, 2);
            populateSelectFromColumn('disabledUsersManufacturerFilter', disabledUsersTable, 4);
            populateSelectFromColumn('disabledUsersModelFilter', disabledUsersTable, 5);

            populateSelectFromColumn('bitLockerCustomerFilter', bitLockerTable, 0);
            populateSelectFromColumn('bitLockerDeviceFilter', bitLockerTable, 1);
            populateSelectFromColumn('bitLockerUserFilter', bitLockerTable, 2);
            populateSelectFromColumn('bitLockerKeyEscrowedFilter', bitLockerTable, 6);
            populateSelectFromColumn('bitLockerSeverityFilter', bitLockerTable, 7);

            populateSelectFromColumn('lapsCustomerFilter', lapsTable, 0);
            populateSelectFromColumn('lapsDeviceFilter', lapsTable, 1);
            populateSelectFromColumn('lapsUserFilter', lapsTable, 2);
            populateSelectFromColumn('lapsOwnerFilter', lapsTable, 4);
            populateSelectFromColumn('lapsSeverityFilter', lapsTable, 8);

            populateSelectFromColumn('deprecatedPlatformFilter', deprecatedTable, 1);
        }

        function populateSelectFromColumn(selectId, table, columnIndex) {
            var values = [...new Set(table.column(columnIndex).data().toArray())].sort();
            var select = `$('#' + selectId);
            values.forEach(function(value) {
                if (value && value.toString().trim() !== '') {
                    select.append(`$('<option>').val(value).text(value));
                }
            });
        }

        // Application Failures filter functions
        window.applyAppFailuresFilters = function() {
            var customerFilter = `$('#appFailuresCustomerFilter').val();
            var appFilter = `$('#appFailuresAppFilter').val();
            var platformFilter = `$('#appFailuresPlatformFilter').val();
            var versionFilter = `$('#appFailuresVersionFilter').val();
            var percentageFilter = `$('#appFailuresPercentageFilter').val();

            appFailuresTable.columns().search('').draw();

            if (customerFilter) appFailuresTable.column(0).search('^' + customerFilter + '`$', true, false);
            if (appFilter) appFailuresTable.column(1).search('^' + appFilter + '`$', true, false);
            if (platformFilter) appFailuresTable.column(2).search('^' + platformFilter + '`$', true, false);
            if (versionFilter) appFailuresTable.column(3).search('^' + versionFilter + '`$', true, false);
            if (percentageFilter) {
                var regex = '';
                if (percentageFilter === '0-20') regex = '^(0|[1-9]|1[0-9]|20)%`$';
                else if (percentageFilter === '20-40') regex = '^(2[0-9]|3[0-9]|40)%`$';
                else if (percentageFilter === '40-60') regex = '^(4[0-9]|5[0-9]|60)%`$';
                else if (percentageFilter === '60-80') regex = '^(6[0-9]|7[0-9]|80)%`$';
                else if (percentageFilter === '80-100') regex = '^(8[0-9]|9[0-9]|100)%`$';
                if (regex) appFailuresTable.column(5).search(regex, true, false);
            }

            appFailuresTable.draw();
        };

        window.clearAppFailuresFilters = function() {
            `$('#appFailuresCustomerFilter, #appFailuresAppFilter, #appFailuresPlatformFilter, #appFailuresVersionFilter, #appFailuresPercentageFilter').val('');
            appFailuresTable.search('').columns().search('').draw();
        };

        // Multiple Users filter functions
        window.applyMultipleUsersFilters = function() {
            var customerFilter = `$('#multipleUsersCustomerFilter').val();
            var deviceFilter = `$('#multipleUsersDeviceFilter').val();
            var userFilter = `$('#multipleUsersPrimaryUserFilter').val();
            var profileFilter = `$('#multipleUsersProfileFilter').val();
            var countFilter = `$('#multipleUsersCountFilter').val();

            multipleUsersTable.columns().search('').draw();

            if (customerFilter) multipleUsersTable.column(0).search('^' + customerFilter + '`$', true, false);
            if (deviceFilter) multipleUsersTable.column(1).search('^' + deviceFilter + '`$', true, false);
            if (userFilter) multipleUsersTable.column(2).search('^' + userFilter + '`$', true, false);
            if (profileFilter) multipleUsersTable.column(3).search('^' + profileFilter + '`$', true, false);
            if (countFilter) {
                if (countFilter === '2') multipleUsersTable.column(4).search('^2`$', true, false);
                else if (countFilter === '3') multipleUsersTable.column(4).search('^3`$', true, false);
                else if (countFilter === '4+') multipleUsersTable.column(4).search('[4-9]|[1-9][0-9]+', true, false);
            }

            multipleUsersTable.draw();
        };

        window.clearMultipleUsersFilters = function() {
            `$('#multipleUsersCustomerFilter, #multipleUsersDeviceFilter, #multipleUsersPrimaryUserFilter, #multipleUsersProfileFilter, #multipleUsersCountFilter').val('');
            multipleUsersTable.search('').columns().search('').draw();
        };

        // No Autopilot filter functions
        window.applyNoAutopilotFilters = function() {
            var customerFilter = `$('#noAutopilotCustomerFilter').val();
            var deviceFilter = `$('#noAutopilotDeviceFilter').val();
            var userFilter = `$('#noAutopilotUserFilter').val();
            var manufacturerFilter = `$('#noAutopilotManufacturerFilter').val();
            var modelFilter = `$('#noAutopilotModelFilter').val();

            noAutopilotTable.columns().search('').draw();

            if (customerFilter) noAutopilotTable.column(0).search('^' + customerFilter + '`$', true, false);
            if (deviceFilter) noAutopilotTable.column(1).search('^' + deviceFilter + '`$', true, false);
            if (userFilter) noAutopilotTable.column(2).search('^' + userFilter + '`$', true, false);
            if (manufacturerFilter) noAutopilotTable.column(4).search('^' + manufacturerFilter + '`$', true, false);
            if (modelFilter) noAutopilotTable.column(5).search('^' + modelFilter + '`$', true, false);

            noAutopilotTable.draw();
        };

        window.clearNoAutopilotFilters = function() {
            `$('#noAutopilotCustomerFilter, #noAutopilotDeviceFilter, #noAutopilotUserFilter, #noAutopilotManufacturerFilter, #noAutopilotModelFilter').val('');
            noAutopilotTable.search('').columns().search('').draw();
        };

        // Inactive Devices filter functions
        window.applyInactiveFilters = function() {
            var customerFilter = `$('#inactiveCustomerFilter').val();
            var deviceFilter = `$('#inactiveDeviceFilter').val();
            var userFilter = `$('#inactiveUserFilter').val();
            var manufacturerFilter = `$('#inactiveManufacturerFilter').val();
            var modelFilter = `$('#inactiveModelFilter').val();
            var inactivityFilter = `$('#inactiveInactivityFilter').val();

            inactiveDevicesTable.columns().search('').draw();

            if (customerFilter) inactiveDevicesTable.column(0).search('^' + customerFilter + '`$', true, false);
            if (deviceFilter) inactiveDevicesTable.column(1).search('^' + deviceFilter + '`$', true, false);
            if (userFilter) inactiveDevicesTable.column(2).search('^' + userFilter + '`$', true, false);
            if (manufacturerFilter) inactiveDevicesTable.column(4).search('^' + manufacturerFilter + '`$', true, false);
            if (modelFilter) inactiveDevicesTable.column(5).search('^' + modelFilter + '`$', true, false);

            inactiveDevicesTable.draw();
        };

        window.clearInactiveFilters = function() {
            `$('#inactiveCustomerFilter, #inactiveDeviceFilter, #inactiveUserFilter, #inactiveManufacturerFilter, #inactiveModelFilter, #inactiveInactivityFilter').val('');
            inactiveDevicesTable.search('').columns().search('').draw();
        };

        // Noncompliant Devices filter functions
        window.applyNoncompliantFilters = function() {
            var customerFilter = `$('#noncompliantCustomerFilter').val();
            var deviceFilter = `$('#noncompliantDeviceFilter').val();
            var userFilter = `$('#noncompliantUserFilter').val();
            var manufacturerFilter = `$('#noncompliantManufacturerFilter').val();
            var modelFilter = `$('#noncompliantModelFilter').val();
            var reasonFilter = `$('#noncompliantReasonFilter').val();

            noncompliantTable.columns().search('').draw();

            if (customerFilter) noncompliantTable.column(0).search('^' + customerFilter + '`$', true, false);
            if (deviceFilter) noncompliantTable.column(1).search('^' + deviceFilter + '`$', true, false);
            if (userFilter) noncompliantTable.column(2).search('^' + userFilter + '`$', true, false);
            if (manufacturerFilter) noncompliantTable.column(4).search('^' + manufacturerFilter + '`$', true, false);
            if (modelFilter) noncompliantTable.column(5).search('^' + modelFilter + '`$', true, false);
            if (reasonFilter) noncompliantTable.column(7).search('^' + reasonFilter + '`$', true, false);

            noncompliantTable.draw();
        };

        window.clearNoncompliantFilters = function() {
            `$('#noncompliantCustomerFilter, #noncompliantDeviceFilter, #noncompliantUserFilter, #noncompliantManufacturerFilter, #noncompliantModelFilter, #noncompliantReasonFilter').val('');
            noncompliantTable.search('').columns().search('').draw();
        };

        // OS Edition Overview filter functions
        window.applyOSEditionFilters = function() {
            var customerFilter = `$('#osEditionCustomerFilter').val();
            var deviceFilter = `$('#osEditionDeviceFilter').val();
            var userFilter = `$('#osEditionUserFilter').val();
            var editionFilter = `$('#osEditionEditionFilter').val();
            var friendlyNameFilter = `$('#osEditionFriendlyNameFilter').val();

            osEditionTable.columns().search('').draw();

            if (customerFilter) osEditionTable.column(0).search('^' + customerFilter + '`$', true, false);
            if (deviceFilter) osEditionTable.column(1).search('^' + deviceFilter + '`$', true, false);
            if (userFilter) osEditionTable.column(2).search('^' + userFilter + '`$', true, false);
            if (editionFilter) osEditionTable.column(3).search('^' + editionFilter + '`$', true, false);
            if (friendlyNameFilter) osEditionTable.column(4).search('^' + friendlyNameFilter + '`$', true, false);

            osEditionTable.draw();
        };

        window.clearOSEditionFilters = function() {
            `$('#osEditionCustomerFilter, #osEditionDeviceFilter, #osEditionUserFilter, #osEditionEditionFilter, #osEditionFriendlyNameFilter').val('');
            osEditionTable.search('').columns().search('').draw();
        };

        // Disabled Primary Users filter functions
        window.applyDisabledUsersFilters = function() {
            var customerFilter = `$('#disabledUsersCustomerFilter').val();
            var deviceFilter = `$('#disabledUsersDeviceFilter').val();
            var userFilter = `$('#disabledUsersUserFilter').val();
            var manufacturerFilter = `$('#disabledUsersManufacturerFilter').val();
            var modelFilter = `$('#disabledUsersModelFilter').val();

            disabledUsersTable.columns().search('').draw();

            if (customerFilter) disabledUsersTable.column(0).search('^' + customerFilter + '`$', true, false);
            if (deviceFilter) disabledUsersTable.column(1).search('^' + deviceFilter + '`$', true, false);
            if (userFilter) disabledUsersTable.column(2).search('^' + userFilter + '`$', true, false);
            if (manufacturerFilter) disabledUsersTable.column(4).search('^' + manufacturerFilter + '`$', true, false);
            if (modelFilter) disabledUsersTable.column(5).search('^' + modelFilter + '`$', true, false);

            disabledUsersTable.draw();
        };

        window.clearDisabledUsersFilters = function() {
            `$('#disabledUsersCustomerFilter, #disabledUsersDeviceFilter, #disabledUsersUserFilter, #disabledUsersManufacturerFilter, #disabledUsersModelFilter').val('');
            disabledUsersTable.search('').columns().search('').draw();
        };

        // BitLocker filter functions
        window.applyBitLockerFilters = function() {
            var customerFilter = `$('#bitLockerCustomerFilter').val();
            var deviceFilter = `$('#bitLockerDeviceFilter').val();
            var userFilter = `$('#bitLockerUserFilter').val();
            var keyEscrowedFilter = `$('#bitLockerKeyEscrowedFilter').val();
            var severityFilter = `$('#bitLockerSeverityFilter').val();

            bitLockerTable.columns().search('').draw();

            if (customerFilter) bitLockerTable.column(0).search('^' + customerFilter + '`$', true, false);
            if (deviceFilter) bitLockerTable.column(1).search('^' + deviceFilter + '`$', true, false);
            if (userFilter) bitLockerTable.column(2).search('^' + userFilter + '`$', true, false);
            if (keyEscrowedFilter) bitLockerTable.column(6).search('^' + keyEscrowedFilter + '`$', true, false);
            if (severityFilter) bitLockerTable.column(7).search(severityFilter, true, false);

            bitLockerTable.draw();
        };

        window.clearBitLockerFilters = function() {
            `$('#bitLockerCustomerFilter, #bitLockerDeviceFilter, #bitLockerUserFilter, #bitLockerKeyEscrowedFilter, #bitLockerSeverityFilter').val('');
            bitLockerTable.search('').columns().search('').draw();
        };

        // Windows LAPS filter functions
        window.applyLapsFilters = function() {
            var customerFilter = `$('#lapsCustomerFilter').val();
            var deviceFilter = `$('#lapsDeviceFilter').val();
            var userFilter = `$('#lapsUserFilter').val();
            var ownerFilter = `$('#lapsOwnerFilter').val();
            var severityFilter = `$('#lapsSeverityFilter').val();

            lapsTable.columns().search('').draw();

            if (customerFilter) lapsTable.column(0).search('^' + customerFilter + '`$', true, false);
            if (deviceFilter) lapsTable.column(1).search('^' + deviceFilter + '`$', true, false);
            if (userFilter) lapsTable.column(2).search('^' + userFilter + '`$', true, false);
            if (ownerFilter) lapsTable.column(4).search('^' + ownerFilter + '`$', true, false);
            if (severityFilter) lapsTable.column(8).search(severityFilter, true, false);

            lapsTable.draw();
        };

        window.clearLapsFilters = function() {
            `$('#lapsCustomerFilter, #lapsDeviceFilter, #lapsUserFilter, #lapsOwnerFilter, #lapsSeverityFilter').val('');
            lapsTable.search('').columns().search('').draw();
        };

        // Deprecated Settings filter functions
        window.applyDeprecatedFilters = function() {
            var platformFilter = `$('#deprecatedPlatformFilter').val();
            deprecatedTable.columns().search('').draw();
            if (platformFilter) deprecatedTable.column(1).search('^' + platformFilter + '`$', true, false);
            deprecatedTable.draw();
        };

        window.clearDeprecatedFilters = function() {
            `$('#deprecatedPlatformFilter').val('');
            deprecatedTable.search('').columns().search('').draw();
        };

        // Auto-apply filters on change - Application Failures
        `$('#appFailuresCustomerFilter, #appFailuresAppFilter, #appFailuresPlatformFilter, #appFailuresVersionFilter, #appFailuresPercentageFilter').on('change', function() {
            applyAppFailuresFilters();
        });

        // Auto-apply filters on change - Multiple Users
        `$('#multipleUsersCustomerFilter, #multipleUsersDeviceFilter, #multipleUsersPrimaryUserFilter, #multipleUsersProfileFilter, #multipleUsersCountFilter').on('change', function() {
            applyMultipleUsersFilters();
        });

        // Auto-apply filters on change - No Autopilot
        `$('#noAutopilotCustomerFilter, #noAutopilotDeviceFilter, #noAutopilotUserFilter, #noAutopilotManufacturerFilter, #noAutopilotModelFilter').on('change', function() {
            applyNoAutopilotFilters();
        });

        // Auto-apply filters on change - Inactive Devices
        `$('#inactiveCustomerFilter, #inactiveDeviceFilter, #inactiveUserFilter, #inactiveManufacturerFilter, #inactiveModelFilter, #inactiveInactivityFilter').on('change', function() {
            applyInactiveFilters();
        });

        // Auto-apply filters on change - Noncompliant Devices
        `$('#noncompliantCustomerFilter, #noncompliantDeviceFilter, #noncompliantUserFilter, #noncompliantManufacturerFilter, #noncompliantModelFilter, #noncompliantReasonFilter').on('change', function() {
            applyNoncompliantFilters();
        });

        // Auto-apply filters on change - OS Edition Overview
        `$('#osEditionCustomerFilter, #osEditionDeviceFilter, #osEditionUserFilter, #osEditionEditionFilter, #osEditionFriendlyNameFilter').on('change', function() {
            applyOSEditionFilters();
        });

        // Auto-apply filters on change - Disabled Primary Users
        `$('#disabledUsersCustomerFilter, #disabledUsersDeviceFilter, #disabledUsersUserFilter, #disabledUsersManufacturerFilter, #disabledUsersModelFilter').on('change', function() {
            applyDisabledUsersFilters();
        });

        // Auto-apply filters on change - BitLocker
        `$('#bitLockerCustomerFilter, #bitLockerDeviceFilter, #bitLockerUserFilter, #bitLockerKeyEscrowedFilter, #bitLockerSeverityFilter').on('change', function() {
            applyBitLockerFilters();
        });

        // Auto-apply filters on change - Windows LAPS
        `$('#lapsCustomerFilter, #lapsDeviceFilter, #lapsUserFilter, #lapsOwnerFilter, #lapsSeverityFilter').on('change', function() {
            applyLapsFilters();
        });

        // Auto-apply filters on change - Deprecated Settings
        `$('#deprecatedPlatformFilter').on('change', function() {
            applyDeprecatedFilters();
        });

        // Show all toggle functions for each table
        `$('#appFailuresShowAllToggle').on('change', function() {
            appFailuresTable.page.len(`$(this).is(':checked') ? -1 : 10).draw();
        });

        `$('#multipleUsersShowAllToggle').on('change', function() {
            multipleUsersTable.page.len(`$(this).is(':checked') ? -1 : 10).draw();
        });

        `$('#noAutopilotShowAllToggle').on('change', function() {
            noAutopilotTable.page.len(`$(this).is(':checked') ? -1 : 10).draw();
        });

        `$('#inactiveDevicesShowAllToggle').on('change', function() {
            inactiveDevicesTable.page.len(`$(this).is(':checked') ? -1 : 10).draw();
        });

        `$('#noncompliantShowAllToggle').on('change', function() {
            noncompliantTable.page.len(`$(this).is(':checked') ? -1 : 10).draw();
        });

        `$('#osEditionShowAllToggle').on('change', function() {
            osEditionTable.page.len(`$(this).is(':checked') ? -1 : 10).draw();
        });

        `$('#disabledUsersShowAllToggle').on('change', function() {
            disabledUsersTable.page.len(`$(this).is(':checked') ? -1 : 10).draw();
        });

        `$('#bitLockerShowAllToggle').on('change', function() {
            bitLockerTable.page.len(`$(this).is(':checked') ? -1 : 10).draw();
        });

        `$('#lapsShowAllToggle').on('change', function() {
            lapsTable.page.len(`$(this).is(':checked') ? -1 : 10).draw();
        });

        `$('#deprecatedShowAllToggle').on('change', function() {
            deprecatedTable.page.len(`$(this).is(':checked') ? -1 : 10).draw();
        });

        // Populate filters after tables are initialized
        setTimeout(function() {
            populateFilters();
        }, 100);
    });
    </script>
"@


    # Report-specific CSS (minimal -- filter bar inline styles only)
    $customCss = @"
    .rk-filter-bar .form-select {
        font-family: 'Geist Mono', ui-monospace, monospace;
        font-size: 0.75rem;
        padding: 4px 8px;
        border-radius: 6px;
    }
"@


    # Generate the full HTML report using the shared template
    $htmlContent = Get-RKSolutionsReportTemplate `
        -TenantName $TenantName `
        -ReportTitle 'Anomalies' `
        -ReportSlug 'intune-anomalies' `
        -Eyebrow 'INTUNE ANOMALIES' `
        -Lede 'Device compliance overview with flagged anomalies across encryption, activity, and application health.' `
        -StatsCardsHtml $statsCardsHtml `
        -BodyContentHtml $bodyContentHtml `
        -CustomCss $customCss `
        -ReportDate $CurrentDate `
        -Tags @('Intune', 'Compliance', 'Security') `
        -StatsClass 'rk-stats-5'

    # Export to HTML file
    $htmlContent | Out-File -FilePath $ExportPath -Encoding utf8

    # Set script-scoped variable for email attachment
    $script:ExportPath = $ExportPath

    Write-Host "INFO: All actions completed successfully."
    Write-Host "INFO: Intune Anomalies Report saved to: $ExportPath" -ForegroundColor Cyan

    # Open the HTML file only if we're not sending email
    if (-not $SendEmail) {
        try { Invoke-Item $ExportPath -ErrorAction Stop }
        catch { Write-Host "Report saved to: $ExportPath (could not open automatically)." -ForegroundColor Yellow }
    }
}