modules/Devolutions.CIEM.PSU/Pages/New-CIEMScanPage.ps1

function New-CIEMScanPage {
    <#
    .SYNOPSIS
        Creates the Scan page for selecting and executing CIEM checks.
    .PARAMETER Navigation
        Array of UDListItem components for sidebar navigation.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [object[]]$Navigation
    )

    New-UDPage -Name 'Scan' -Url '/ciem/scan' -Content {
        New-UDTypography -Text 'Run CIEM Scan' -Variant 'h4' -Style @{ marginBottom = '20px'; marginTop = '10px' }
        New-UDTypography -Text 'Configure and execute a CIEM security scan against your cloud environment' -Variant 'subtitle1' -Style @{ marginBottom = '30px'; color = '#666' }

        # Check Selection Card
        New-UDCard -Title 'Check Selection' -Content {
            # Check selection data grid with checkboxes
            New-UDDynamic -Id 'checkSelectionGrid' -Content {

                $allChecks = @(Get-CIEMCheck)

                # Initialize session state on first load
                if ($null -eq $Session:CheckStatusFilter) {
                    $Session:CheckStatusFilter = 'enabled'
                }

                # Selection summary
                New-UDDynamic -Id 'selectionSummary' -Content {
    
                    $checks = @(Get-CIEMCheck)
                    $enabledCount = @($checks | Where-Object { -not $_.Disabled }).Count
                    $disabledCount = @($checks | Where-Object { $_.Disabled }).Count
                    $selectedCount = @($Session:SelectedCheckIds).Count
                    New-UDElement -Tag 'div' -Attributes @{ style = @{ marginBottom = '8px' } } -Content {
                        New-UDStack -Direction 'row' -Spacing 2 -AlignItems 'center' -Content {
                            New-UDTypography -Text "$selectedCount / $enabledCount enabled checks selected ($disabledCount disabled)" -Variant 'body2' -Style @{ color = '#666' }
                        }
                    }
                }

                # Status filter
                New-UDElement -Tag 'div' -Attributes @{ style = @{ marginBottom = '12px' } } -Content {
                    New-UDStack -Direction 'row' -Spacing 2 -AlignItems 'center' -Content {
                        New-UDTypography -Text 'Status:' -Variant 'body2' -Style @{ color = '#666'; marginRight = '4px' }
                        New-UDElement -Tag 'div' -Attributes @{ style = @{ minWidth = '140px' } } -Content {
                            New-UDSelect -Id 'checkStatusFilter' -DefaultValue $Session:CheckStatusFilter -OnChange {
                                $Session:CheckStatusFilter = $EventData
                                Sync-UDElement -Id 'checkSelectionGrid'
                            } -Option {
                                New-UDSelectOption -Name 'Enabled' -Value 'enabled'
                                New-UDSelectOption -Name 'Disabled' -Value 'disabled'
                                New-UDSelectOption -Name 'All' -Value 'all'
                            }
                        }
                    }
                }

                New-UDDataGrid -Id 'checkSelector' -LoadRows {
    
                    $checks = @(Get-CIEMCheck)

                    # Apply status filter
                    $statusFilter = $Session:CheckStatusFilter
                    if ($statusFilter -eq 'enabled') {
                        $checks = @($checks | Where-Object { -not $_.Disabled })
                    } elseif ($statusFilter -eq 'disabled') {
                        $checks = @($checks | Where-Object { $_.Disabled })
                    }

                    $checksData = $checks | ForEach-Object {
                        @{
                            id              = $_.Id
                            checkId         = $_.Id
                            title           = $_.Title
                            description     = $_.Description
                            risk            = $_.Risk
                            provider        = [string]$_.Provider
                            service         = [string]$_.Service
                            severity        = ([string]$_.Severity -replace '^(.)', { $_.Groups[1].Value.ToUpper() })
                            relatedUrl      = $_.RelatedUrl
                            remediationText = $_.Remediation.Text
                            remediationUrl  = $_.Remediation.Url
                            disabled        = [bool]$_.Disabled
                        }
                    }
                    @($checksData) | Out-UDDataGridData -Context $EventData -TotalRows @($checksData).Count
                } -CheckboxSelection -CheckboxSelectionVisibleOnly -OnSelectionChange {
                    $Session:SelectedCheckIds = @($EventData)
                    Sync-UDElement -Id 'selectionSummary'
                } -Columns @(
                    New-UDDataGridColumn -Field 'info' -HeaderName 'Info' -Width 60 -Render {
                        New-UDIconButton -Icon (New-UDIcon -Icon 'InfoCircle') -Size 'small' -OnClick {
                            Show-UDModal -Header {
                                New-UDTypography -Text $EventData.title -Variant 'h6'
                            } -Content {
                                $sev = $EventData.severity.ToUpper()
                                $sevColor = Get-SeverityColor -Severity $sev
                                New-UDElement -Tag 'div' -Attributes @{ style = @{ marginBottom = '16px' } } -Content {
                                    New-UDStack -Direction 'row' -Spacing 2 -AlignItems 'center' -Content {
                                        New-UDChip -Label $sev -Style @{ backgroundColor = $sevColor; color = 'white' }
                                        New-UDChip -Label $EventData.provider -Variant 'outlined'
                                        New-UDChip -Label $EventData.service -Variant 'outlined'
                                    }
                                }
                                New-UDTypography -Text 'Description' -Variant 'subtitle2' -Style @{ fontWeight = 'bold'; marginBottom = '4px' }
                                New-UDTypography -Text $EventData.description -Variant 'body2' -Style @{ marginBottom = '16px' }
                                New-UDTypography -Text 'Risk' -Variant 'subtitle2' -Style @{ fontWeight = 'bold'; marginBottom = '4px' }
                                New-UDTypography -Text $EventData.risk -Variant 'body2' -Style @{ marginBottom = '16px' }
                                if ($EventData.remediationText) {
                                    New-UDTypography -Text 'Remediation' -Variant 'subtitle2' -Style @{ fontWeight = 'bold'; marginBottom = '4px' }
                                    New-UDTypography -Text $EventData.remediationText -Variant 'body2' -Style @{ marginBottom = '16px' }
                                }
                                New-UDTypography -Text 'Check ID' -Variant 'subtitle2' -Style @{ fontWeight = 'bold'; marginBottom = '4px' }
                                New-UDTypography -Text $EventData.checkId -Variant 'body2' -Style @{ marginBottom = '16px'; fontFamily = 'monospace' }
                            } -Footer {
                                New-UDStack -Direction 'row' -Spacing 2 -Content {
                                    if ($EventData.relatedUrl) {
                                        New-UDButton -Text 'Documentation' -Variant 'outlined' -OnClick { Invoke-UDRedirect -Url $EventData.relatedUrl -OpenInNewWindow }
                                    }
                                    if ($EventData.remediationUrl) {
                                        New-UDButton -Text 'Remediation' -Variant 'outlined' -OnClick { Show-UDToast -Message 'This is where we could link to Devolutions PAM articles on how PAM remediates this.' -Duration 5000 }
                                    }
                                    New-UDButton -Text 'Close' -OnClick { Hide-UDModal }
                                }
                            } -FullWidth -MaxWidth 'md' -Dividers
                        }
                    }
                    New-UDDataGridColumn -Field 'severity' -HeaderName 'Severity' -Width 110 -Render {
                        $sev = $EventData.severity.ToUpper()
                        if ($EventData.disabled) {
                            New-UDChip -Label $sev -Style @{ backgroundColor = '#e0e0e0'; color = '#bbb' }
                        } else {
                            $color = Get-SeverityColor -Severity $sev
                            New-UDChip -Label $sev -Style @{ backgroundColor = $color; color = 'white' }
                        }
                    }
                    New-UDDataGridColumn -Field 'provider' -HeaderName 'Provider' -Width 100 -Render {
                        $textColor = if ($EventData.disabled) { '#bbb' } else { 'inherit' }
                        New-UDElement -Tag 'span' -Attributes @{ style = @{ color = $textColor } } -Content { $EventData.provider }
                    }
                    New-UDDataGridColumn -Field 'service' -HeaderName 'Service' -Width 130 -Render {
                        $textColor = if ($EventData.disabled) { '#bbb' } else { 'inherit' }
                        New-UDElement -Tag 'span' -Attributes @{ style = @{ color = $textColor } } -Content { $EventData.service }
                    }
                    New-UDDataGridColumn -Field 'title' -HeaderName 'Title' -Flex 1 -Render {
                        $textColor = if ($EventData.disabled) { '#bbb' } else { 'inherit' }
                        New-UDElement -Tag 'span' -Attributes @{ style = @{ color = $textColor } } -Content { $EventData.title }
                    }
                    New-UDDataGridColumn -Field 'checkId' -HeaderName 'Check ID' -Width 280 -Render {
                        $textColor = if ($EventData.disabled) { '#bbb' } else { 'inherit' }
                        New-UDElement -Tag 'span' -Attributes @{ style = @{ color = $textColor } } -Content { $EventData.checkId }
                    }
                ) -DisableRowSelectionOnClick -AutoHeight $true -Pagination -PageSize 25 -ShowQuickFilter -Density 'compact'
            }

            # Scan Progress Area - stores scan state and results
            New-UDElement -Tag 'div' -Id 'scanProgressArea' -Content {
                # Initially empty - populated during scan via Set-UDElement
            }

            # Action Buttons
            New-UDElement -Tag 'div' -Attributes @{ style = @{ marginTop = '16px' } } -Content {
                New-UDButton -Id 'startScanBtn' -Text 'Start Scan' -Variant 'contained' -Color 'primary' -ShowLoading -OnClick {
                    try {
                        Write-CIEMLog -Message "Start Scan button clicked" -Severity INFO -Component 'PSU-ScanPage'

                        # Read selected check IDs from session state (synced by OnSelectionChange)
                        $selectedCheckIds = @($Session:SelectedCheckIds | Where-Object { $_ })

                        if ($selectedCheckIds.Count -eq 0) {
                            Show-UDToast -Message 'Please select at least one check.' -Duration 5000 -BackgroundColor '#ff9800'
                            return
                        }

                        # Query only the selected checks to get provider/service metadata
                        $selectedChecks = @(Get-CIEMCheck -CheckId $selectedCheckIds | Where-Object { -not $_.Disabled })

                        if ($selectedChecks.Count -eq 0) {
                            Show-UDToast -Message 'All selected checks are disabled.' -Duration 5000 -BackgroundColor '#ff9800'
                            return
                        }

                        $selectedCheckIds = @($selectedChecks | Select-Object -ExpandProperty Id)
                        $selectedProviders = @($selectedChecks | Select-Object -ExpandProperty Provider -Unique)
                        $selectedServices = @($selectedChecks | Select-Object -ExpandProperty Service -Unique)
                        Write-CIEMLog -Message "Scan config: Checks=$($selectedCheckIds.Count), Providers=$($selectedProviders -join ','), Services=$($selectedServices -join ',')" -Severity INFO -Component 'PSU-ScanPage'

                        Show-UDToast -Message "Starting CIEM scan: $($selectedCheckIds.Count) checks across $($selectedServices -join ', ')" -Duration 3000

                        # PSU doesn't pass -Parameters to module command scripts, so use cache
                        $scanConfig = @{
                            Provider      = $selectedProviders
                            Service       = $selectedServices
                            CheckId       = $selectedCheckIds
                            IncludePassed = $true
                        }
                        Set-PSUCache -Key $script:ScanConfigCacheKey -Value $scanConfig -Integrated

                        Write-CIEMLog -Message "Launching CIEM Scan job for providers: $($selectedProviders -join ', ')..." -Severity INFO -Component 'PSU-ScanPage'

                        $scanRun = Invoke-CIEMJobWithProgress `
                            -ScriptName 'Devolutions.CIEM\New-CIEMScanRun' `
                            -ProgressElementId 'scanProgressArea' `
                            -DisableElementIds @('startScanBtn') `
                            -MaxPollSeconds 1800

                        if (-not $scanRun) {
                            throw "Scan job completed but returned no pipeline output."
                        }

                        $allResults = @($scanRun.ScanResults)
                        $failedCount = $scanRun.FailedResults
                        $passedCount = $scanRun.PassedResults
                        $manualCount = $scanRun.ManualResults
                        $skippedCount = $scanRun.SkippedResults
                        $totalCount = $scanRun.TotalResults
                        $durationStr = $scanRun.Duration

                        Write-CIEMLog -Message "Scan complete. Results: $($allResults.Count), Duration: $durationStr" -Severity INFO -Component 'PSU-ScanPage'

                        # Store in session for quick page access
                        $Session:CIEMScanResults = $allResults
                        $Session:CIEMScanTimestamp = $scanRun.EndTime
                        $Session:CIEMIncludePassed = $true

                        Write-CIEMLog -Message "Persisted $($allResults.Count) scan results (ScanRunId: $($scanRun.Id))" -Severity INFO -Component 'PSU-ScanPage'

                        # Update progress area with results summary
                        $summaryParts = @("Duration: $durationStr", "Total: $totalCount", "Failed: $failedCount", "Passed: $passedCount")
                        if ($manualCount -gt 0) { $summaryParts += "Manual: $manualCount" }
                        if ($skippedCount -gt 0) { $summaryParts += "Skipped: $skippedCount" }
                        $summaryText = $summaryParts -join ' | '

                        Set-UDElement -Id 'scanProgressArea' -Content {
                            New-CIEMSuccessContent -Text 'Scan Complete!' -Details "$summaryText`nView detailed results on the Scan History page."
                        }

                        # Toast notifications
                        $toastParts = @("Scan complete!")
                        if ($failedCount -gt 0) { $toastParts += "$failedCount failed" }
                        if ($passedCount -gt 0) { $toastParts += "$passedCount passed" }
                        if ($manualCount -gt 0) { $toastParts += "$manualCount manual review" }
                        Show-UDToast -Message ($toastParts -join ' | ') -Duration 5000 -BackgroundColor '#4caf50'
                        Show-UDToast -Message 'View detailed results on the Scan History page.' -Duration 5000
                    }
                    catch {
                        Write-CIEMLog -Message "Scan failed: $($_.Exception.Message)" -Severity ERROR -Component 'PSU-ScanPage'
                        Write-CIEMLog -Message "Stack: $($_.ScriptStackTrace)" -Severity DEBUG -Component 'PSU-ScanPage'

                        Set-UDElement -Id 'scanProgressArea' -Content {
                            New-CIEMErrorContent -Text 'Scan Failed' -Details $_.Exception.Message
                        }

                        Show-UDToast -Message "Scan failed: $($_.Exception.Message)" -Duration 8000 -BackgroundColor '#f44336'
                    }
                }
            }
        }

    } -Navigation $Navigation -NavigationLayout permanent
}