<#
.SYNOPSIS
    Manages the business logic for the 'Windows Settings' tab in the FFU Builder UI.
.DESCRIPTION
    This module contains all the functions and data required to populate and manage the controls on the 'Windows Settings' tab. It handles dynamic updates for Windows Release, Version, SKU, and Architecture ComboBoxes based on user input, such as specifying an ISO path. It also includes logic for populating available languages, media types, and the grid of optional Windows features.
#>

# --------------------------------------------------------------------------
# SECTION: Module Variables (Static Data)
# --------------------------------------------------------------------------

$script:allowedFeatures = @(
    "AppServerClient", "Client-DeviceLockdown", "Client-EmbeddedBootExp", "Client-EmbeddedLogon",
    "Client-EmbeddedShellLauncher", "Client-KeyboardFilter", "Client-ProjFS", "Client-UnifiedWriteFilter",
    "Containers", "Containers-DisposableClientVM", "Containers-HNS", "Containers-SDN", "DataCenterBridging",
    "DirectoryServices-ADAM-Client", "DirectPlay", "HostGuardian", "HypervisorPlatform", "IIS-ApplicationDevelopment",
    "IIS-ApplicationInit", "IIS-ASP", "IIS-ASPNET45", "IIS-BasicAuthentication", "IIS-CertProvider",
    "IIS-CGI", "IIS-ClientCertificateMappingAuthentication", "IIS-CommonHttpFeatures", "IIS-CustomLogging",
    "IIS-DefaultDocument", "IIS-DirectoryBrowsing", "IIS-DigestAuthentication", "IIS-ESP", "IIS-FTPServer",
    "IIS-FTPExtensibility", "IIS-FTPSvc", "IIS-HealthAndDiagnostics", "IIS-HostableWebCore", "IIS-HttpCompressionDynamic",
    "IIS-HttpCompressionStatic", "IIS-HttpErrors", "IIS-HttpLogging", "IIS-HttpRedirect", "IIS-HttpTracing",
    "IIS-IPSecurity", "IIS-IIS6ManagementCompatibility", "IIS-IISCertificateMappingAuthentication",
    "IIS-ISAPIExtensions", "IIS-ISAPIFilter", "IIS-LoggingLibraries", "IIS-ManagementConsole", "IIS-ManagementService",
    "IIS-ManagementScriptingTools", "IIS-Metabase", "IIS-NetFxExtensibility", "IIS-NetFxExtensibility45",
    "IIS-ODBCLogging", "IIS-Performance", "IIS-RequestFiltering", "IIS-RequestMonitor", "IIS-Security", "IIS-ServerSideIncludes",
    "IIS-StaticContent", "IIS-URLAuthorization", "IIS-WebDAV", "IIS-WebServer", "IIS-WebServerManagementTools",
    "IIS-WebServerRole", "IIS-WebSockets", "LegacyComponents", "MediaPlayback", "Microsoft-Hyper-V", "Microsoft-Hyper-V-All",
    "Microsoft-Hyper-V-Hypervisor", "Microsoft-Hyper-V-Management-Clients", "Microsoft-Hyper-V-Management-PowerShell",
    "Microsoft-Hyper-V-Services", "Microsoft-Windows-Subsystem-Linux", "MSMQ-ADIntegration", "MSMQ-Container", "MSMQ-DCOMProxy",
    "MSMQ-HTTP", "MSMQ-Multicast", "MSMQ-Server", "MSMQ-Triggers", "MultiPoint-Connector", "MultiPoint-Connector-Services",
    "MultiPoint-Tools", "NetFx3", "NetFx4-AdvSrvs", "NetFx4Extended-ASPNET45", "NFS-Administration", "Printing-Foundation-Features",
    "Printing-Foundation-InternetPrinting-Client", "Printing-Foundation-LPDPrintService", "Printing-Foundation-LPRPortMonitor",
    "Printing-PrintToPDFServices-Features", "Printing-XPSServices-Features", "SearchEngine-Client-Package",
    "ServicesForNFS-ClientOnly", "SimpleTCP", "SMB1Protocol", "SMB1Protocol-Client", "SMB1Protocol-Deprecation",
    "SMB1Protocol-Server", "SmbDirect", "TFTP", "TelnetClient", "TIFFIFilter", "VirtualMachinePlatform", "WAS-ConfigurationAPI",
    "WAS-NetFxEnvironment", "WAS-ProcessModel", "WAS-WindowsActivationService", "WCF-HTTP-Activation", "WCF-HTTP-Activation45",
    "WCF-MSMQ-Activation45", "WCF-MSMQ-Activation", "WCF-NonHTTP-Activation", "WCF-Pipe-Activation45", "WCF-Services45",
    "WCF-TCP-Activation45", "WCF-TCP-PortSharing45", "Windows-Defender-ApplicationGuard",
    "Windows-Defender-Default-Definitions", "Windows-Identity-Foundation", "WindowsMediaPlayer", "WorkFolders-Client"
)

$script:skuList = @(
    'Home',
    'Home N',
    'Home Single Language',
    'Education',
    'Education N',
    'Pro',
    'Pro N',
    'Pro Education',
    'Pro Education N',
    'Pro for Workstations',
    'Pro N for Workstations',
    'Enterprise',
    'Enterprise N',
    'Enterprise 2016 LTSB',
    'Enterprise N 2016 LTSB',
    'Enterprise LTSC',
    'Enterprise N LTSC',
    'IoT Enterprise LTSC',
    'IoT Enterprise N LTSC',
    'Standard',
    'Standard (Desktop Experience)',
    'Datacenter',
    'Datacenter (Desktop Experience)'
)

$script:allowedLangs = @(
    'ar-sa',
    'bg-bg',
    'cs-cz',
    'da-dk',
    'de-de',
    'el-gr',
    'en-gb',
    'en-us',
    'es-es',
    'es-mx',
    'et-ee',
    'fi-fi',
    'fr-ca',
    'fr-fr',
    'he-il',
    'hr-hr',
    'hu-hu',
    'it-it',
    'ja-jp',
    'ko-kr',
    'lt-lt',
    'lv-lv',
    'nb-no',
    'nl-nl',
    'pl-pl',
    'pt-br',
    'pt-pt',
    'ro-ro',
    'ru-ru',
    'sk-sk',
    'sl-si',
    'sr-latn-rs',
    'sv-se',
    'th-th',
    'tr-tr',
    'uk-ua',
    'zh-cn',
    'zh-tw'
)

$script:allWindowsReleases = @(
    [PSCustomObject]@{ Display = "Windows 10"; Value = 10 },
    [PSCustomObject]@{ Display = "Windows 11"; Value = 11 },
    [PSCustomObject]@{ Display = "Windows Server 2016"; Value = 2016 },
    [PSCustomObject]@{ Display = "Windows Server 2019"; Value = 2019 },
    [PSCustomObject]@{ Display = "Windows Server 2022"; Value = 2022 },
    [PSCustomObject]@{ Display = "Windows Server 2025"; Value = 2025 },
    [PSCustomObject]@{ Display = "Windows 10 LTSB 2016"; Value = 2016 }, # Changed Value from 1607
    [PSCustomObject]@{ Display = "Windows 10 LTSC 2019"; Value = 2019 }, # Changed Value from 1809
    [PSCustomObject]@{ Display = "Windows 10 LTSC 2021"; Value = 2021 },
    [PSCustomObject]@{ Display = "Windows 11 LTSC 2024"; Value = 2024 }
)

$script:mctWindowsReleases = @(
    [PSCustomObject]@{ Display = "Windows 10"; Value = 10 },
    [PSCustomObject]@{ Display = "Windows 11"; Value = 11 }
)

$script:windowsVersionMap = @{
    10   = @("22H2")
    11   = @("25H2", "24H2", "23H2", "22H2")
    2016 = @("1607") # Windows 10 LTSB 2016 & Server 2016
    2019 = @("1809") # Windows 10 LTSC 2019 & Server 2019
    # Note: Server 2016 and LTSB 2016 now share the key 2016, mapping to version "1607"
    # Note: Server 2019 and LTSC 2019 now share the key 2019, mapping to version "1809"
    2021 = @("21H2") # LTSC 2021
    2022 = @("21H2") # Server 2022
    2024 = @("24H2") # LTSC 2024
    2025 = @("24H2") # Server 2025
}

# SKU Groups
$script:clientSKUs = @(
    'Home',
    'Home N',
    'Home Single Language',
    'Education',
    'Education N',
    'Pro',
    'Pro N',
    'Pro Education',
    'Pro Education N',
    'Pro for Workstations',
    'Pro N for Workstations',
    'Enterprise',
    'Enterprise N'
)

$script:serverSKUs = @(
    'Standard',
    'Standard (Desktop Experience)',
    'Datacenter',
    'Datacenter (Desktop Experience)'
)

$script:ltsc2016SKUs = @(
    'Enterprise 2016 LTSB',
    'Enterprise N 2016 LTSB'
)

$script:ltscGenericSKUs = @( # For LTSC 2019, 2021, 2024
    'Enterprise LTSC',
    'Enterprise N LTSC'
)

$script:iotLtscSKUs = @(
    'IoT Enterprise LTSC',
    'IoT Enterprise N LTSC'
)

# Map Windows Release Values to their corresponding SKU lists
$script:windowsReleaseSkuMap = @{
    10   = $script:clientSKUs # Windows 10 Client
    11   = $script:clientSKUs # Windows 11 Client
    2016 = $script:serverSKUs # Windows Server 2016 (LTSB 2016 handled by Get-AvailableSkusForRelease)
    2019 = $script:serverSKUs # Windows Server 2019 (LTSC 2019 handled by Get-AvailableSkusForRelease)
    2022 = $script:serverSKUs # Windows Server 2022
    2025 = $script:serverSKUs # Windows Server 2025
    2021 = $script:ltscGenericSKUs + $script:iotLtscSKUs # Windows 10 LTSC 2021
    2024 = $script:ltscGenericSKUs + $script:iotLtscSKUs # Windows 10 LTSC 2024
    # Note: LTSC 2016 and LTSC 2019 SKUs are now conditionally returned by Get-AvailableSkusForRelease
}

# --------------------------------------------------------------------------
# SECTION: Functions
# --------------------------------------------------------------------------

# Function to return the default settings and static lists
function Get-WindowsSettingsDefaults {
    [CmdletBinding()]
    param()

    return [PSCustomObject]@{
        DefaultISOPath          = ""
        DefaultWindowsArch      = "x64"
        DefaultWindowsLang      = "en-us"
        DefaultWindowsSKU       = "Pro"
        DefaultMediaType        = "Consumer"
        DefaultOptionalFeatures = ""
        DefaultProductKey       = ""
        AllowedFeatures         = $script:allowedFeatures
        AllowedLanguages        = $script:allowedLangs
        AllowedArchitectures    = @('x86', 'x64', 'arm64')
        AllowedMediaTypes       = @('Consumer', 'Business')
        SkuList                 = $script:skuList
        AllWindowsReleases      = $script:allWindowsReleases
        MctWindowsReleases      = $script:mctWindowsReleases
        WindowsVersionMap       = $script:windowsVersionMap
        ClientSKUs              = $script:clientSKUs
        ServerSKUs              = $script:serverSKUs
        Ltsc2016SKUs            = $script:ltsc2016SKUs
        LtscGenericSKUs         = $script:ltscGenericSKUs
        IotLtscSKUs             = $script:iotLtscSKUs
        WindowsReleaseSkuMap    = $script:windowsReleaseSkuMap
    }
}

# Function to get the appropriate list of Windows Releases based on ISO path
function Get-AvailableWindowsReleases {
    [CmdletBinding()]
    param(
        [string]$IsoPath,
        [Parameter(Mandatory = $true)]
        [psobject]$State
    )

    if (-not [string]::IsNullOrEmpty($IsoPath) -and $IsoPath.EndsWith('.iso', [System.StringComparison]::OrdinalIgnoreCase)) {
        return $State.Defaults.WindowsSettingsDefaults.AllWindowsReleases
    }
    else {
        return $State.Defaults.WindowsSettingsDefaults.MctWindowsReleases
    }
}

# Function to get available Windows Versions for a given release and ISO path
function Get-AvailableWindowsVersions {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [int]$SelectedRelease,

        [string]$IsoPath,
        [Parameter(Mandatory = $true)]
        [psobject]$State
    )

    $result = [PSCustomObject]@{
        Versions       = @()
        DefaultVersion = $null
        IsEnabled      = $false
    }

    if (-not $State.Defaults.WindowsSettingsDefaults.WindowsVersionMap.ContainsKey($SelectedRelease)) {
        return $result
    }

    $validVersions = $State.Defaults.WindowsSettingsDefaults.WindowsVersionMap[$SelectedRelease]

    if (-not [string]::IsNullOrEmpty($IsoPath) -and $IsoPath.EndsWith('.iso', [System.StringComparison]::OrdinalIgnoreCase)) {
        # Logic for when an ISO is specified
        $result.Versions = $validVersions
        # Set default selection logic (e.g., latest for Win11)
        if ($SelectedRelease -eq 11) {
            if ($validVersions -contains "25H2") {
                $result.DefaultVersion = "25H2"
            }
            elseif ($validVersions -contains "24H2") {
                $result.DefaultVersion = "24H2"
            }
        }
        if (-not $result.DefaultVersion -and $validVersions.Count -gt 0) {
            $result.DefaultVersion = $validVersions[0]
        }
        $result.IsEnabled = $true
    }
    else {
        # Logic for when no ISO is specified (MCT scenario)
        switch ($SelectedRelease) {
            10 { $result.DefaultVersion = "22H2" }
            11 { $result.DefaultVersion = "25H2" }
            # Server versions typically require an ISO, but handle just in case
            2016 { $result.DefaultVersion = "1607" }
            2019 { $result.DefaultVersion = "1809" }
            2022 { $result.DefaultVersion = "21H2" }
            2025 { $result.DefaultVersion = "24H2" }
            default {
                if ($validVersions.Count -gt 0) { $result.DefaultVersion = $validVersions[0] }
            }
        }
        $result.Versions = @($result.DefaultVersion) # Only the default is available/relevant
        $result.IsEnabled = $false # Combo should be disabled
    }

    return $result
}

# Function to get available SKUs for a given Windows Release value and display name
function Get-AvailableSkusForRelease {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [int]$SelectedReleaseValue,

        [Parameter(Mandatory)]
        [string]$SelectedReleaseDisplayName,
        [Parameter(Mandatory = $true)]
        [psobject]$State
    )

    WriteLog "Get-AvailableSkusForRelease: Getting SKUs for Release Value '$SelectedReleaseValue', Display Name '$SelectedReleaseDisplayName'."

    # Handle LTSC 2016 specifically
    if ($SelectedReleaseValue -eq 2016 -and $SelectedReleaseDisplayName -like '*LTSB*') {
        WriteLog "Get-AvailableSkusForRelease: Matched LTSB 2016. Returning LTSC 2016 SKUs."
        return $State.Defaults.WindowsSettingsDefaults.Ltsc2016SKUs
    }
    # Handle LTSC 2019 specifically
    # Ensure "Server" is not in the display name to avoid matching "Windows Server 2019"
    elseif ($SelectedReleaseValue -eq 2019 -and $SelectedReleaseDisplayName -like '*LTSC*' -and $SelectedReleaseDisplayName -notlike '*Server*') {
        WriteLog "Get-AvailableSkusForRelease: Matched LTSC 2019. Returning generic LTSC SKUs (including IoT)."
        # Assuming LTSC 2019 uses the generic LTSC SKUs + IoT LTSC SKUs
        return ($State.Defaults.WindowsSettingsDefaults.LtscGenericSKUs + $State.Defaults.WindowsSettingsDefaults.IotLtscSKUs | Select-Object -Unique)
    }
    # For all other cases, use the main SKU map
    elseif ($State.Defaults.WindowsSettingsDefaults.WindowsReleaseSkuMap.ContainsKey($SelectedReleaseValue)) {
        $availableSkus = $State.Defaults.WindowsSettingsDefaults.WindowsReleaseSkuMap[$SelectedReleaseValue]
        WriteLog "Get-AvailableSkusForRelease: Found $($availableSkus.Count) SKUs for Release '$SelectedReleaseValue' using standard map."
        return $availableSkus
    }
    else {
        WriteLog "Get-AvailableSkusForRelease: Warning - Release Value '$SelectedReleaseValue' not found in SKU map. Returning default client SKUs."
        # Fallback to a default list (e.g., client SKUs) or an empty list
        return $State.Defaults.WindowsSettingsDefaults.ClientSKUs
    }
}

# Function to refresh the Windows Release ComboBox based on ISO path
function Update-WindowsReleaseCombo {
    param(
        [string]$isoPath,
        [Parameter(Mandatory = $true)]
        [psobject]$State
    )

    if (-not $State.Controls.cmbWindowsRelease) { return }

    $oldSelectedItemValue = $null
    if ($null -ne $State.Controls.cmbWindowsRelease.SelectedItem) {
        $oldSelectedItemValue = $State.Controls.cmbWindowsRelease.SelectedItem.Value
    }

    # Get the appropriate list of releases from the helper module
    $availableReleases = Get-AvailableWindowsReleases -IsoPath $isoPath -State $State

    # Update the ComboBox ItemsSource
    $State.Controls.cmbWindowsRelease.ItemsSource = $availableReleases
    $State.Controls.cmbWindowsRelease.DisplayMemberPath = 'Display'
    $State.Controls.cmbWindowsRelease.SelectedValuePath = 'Value'

    # Try to re-select the previously selected item, or default
    $itemToSelect = $availableReleases | Where-Object { $_.Value -eq $oldSelectedItemValue } | Select-Object -First 1
    if ($null -ne $itemToSelect) {
        $State.Controls.cmbWindowsRelease.SelectedItem = $itemToSelect
    }
    elseif ($availableReleases.Count -gt 0) {
        # Default to Windows 11 if available, otherwise the first item
        $defaultItem = $availableReleases | Where-Object { $_.Value -eq 11 } | Select-Object -First 1
        if ($null -eq $defaultItem) {
            $defaultItem = $availableReleases[0]
        }
        $State.Controls.cmbWindowsRelease.SelectedItem = $defaultItem
    }
    else {
        # No items available (should not happen with current logic)
        $State.Controls.cmbWindowsRelease.SelectedIndex = -1
    }
}

# Function to refresh the Windows Version ComboBox based on selected release and ISO path
function Update-WindowsVersionCombo {
    param(
        [int]$selectedRelease,
        [string]$isoPath,
        [Parameter(Mandatory = $true)]
        [psobject]$State
    )

    $combo = $State.Controls.cmbWindowsVersion 
    if (-not $combo) { return } 

    # Get available versions and default from the helper module
    $versionData = Get-AvailableWindowsVersions -SelectedRelease $selectedRelease -IsoPath $isoPath -State $State

    # Update the ComboBox ItemsSource and IsEnabled state
    $combo.ItemsSource = $versionData.Versions
    $combo.IsEnabled = $versionData.IsEnabled

    # Set the selected item
    if ($null -ne $versionData.DefaultVersion -and $versionData.Versions -contains $versionData.DefaultVersion) {
        $combo.SelectedItem = $versionData.DefaultVersion
    }
    elseif ($versionData.Versions.Count -gt 0) {
        $combo.SelectedIndex = 0 
    }
    else {
        $combo.SelectedIndex = -1 # No items available
    }
}

# Function to refresh the Windows SKU ComboBox based on selected release
function Update-WindowsSkuCombo {
    param(
        [Parameter(Mandatory = $true)]
        [psobject]$State
    )

    $skuCombo = $State.Controls.cmbWindowsSKU
    if (-not $skuCombo) {
        WriteLog "Update-WindowsSkuCombo: SKU ComboBox not found."
        return
    }

    $releaseCombo = $State.Controls.cmbWindowsRelease
    if (-not $releaseCombo -or $null -eq $releaseCombo.SelectedItem) {
        WriteLog "Update-WindowsSkuCombo: Windows Release ComboBox not found or no item selected. Cannot update SKUs."
        $skuCombo.ItemsSource = @() # Clear SKUs
        $skuCombo.SelectedIndex = -1
        return
    }

    $selectedReleaseItem = $releaseCombo.SelectedItem
    $selectedReleaseValue = $selectedReleaseItem.Value
    $selectedReleaseDisplayName = $selectedReleaseItem.Display

    $previousSelectedSku = $null
    if ($null -ne $skuCombo.SelectedItem) {
        $previousSelectedSku = $skuCombo.SelectedItem
    }

    WriteLog "Update-WindowsSkuCombo: Updating SKUs for Release Value '$selectedReleaseValue' (Display: '$selectedReleaseDisplayName')."
    # Call Get-AvailableSkusForRelease with both Value and DisplayName
    $availableSkus = Get-AvailableSkusForRelease -SelectedReleaseValue $selectedReleaseValue -SelectedReleaseDisplayName $selectedReleaseDisplayName -State $State

    $skuCombo.ItemsSource = $availableSkus
    WriteLog "Update-WindowsSkuCombo: Set ItemsSource with $($availableSkus.Count) SKUs."

    # Attempt to re-select the previous SKU, or "Pro", or the first available
    if ($null -ne $previousSelectedSku -and $availableSkus -contains $previousSelectedSku) {
        $skuCombo.SelectedItem = $previousSelectedSku
        WriteLog "Update-WindowsSkuCombo: Re-selected previous SKU '$previousSelectedSku'."
    }
    elseif ($availableSkus -contains "Pro") {
        $skuCombo.SelectedItem = "Pro"
        WriteLog "Update-WindowsSkuCombo: Selected default SKU 'Pro'."
    }
    elseif ($availableSkus.Count -gt 0) {
        $skuCombo.SelectedIndex = 0
        WriteLog "Update-WindowsSkuCombo: Selected first available SKU '$($skuCombo.SelectedItem)'."
    }
    else {
        $skuCombo.SelectedIndex = -1 # No SKUs available
        WriteLog "Update-WindowsSkuCombo: No SKUs available for Release '$selectedReleaseValue' (Display: '$selectedReleaseDisplayName')."
    }
}
    
# Function to refresh the Windows Architecture ComboBox based on selected release, version, and SKU
function Update-WindowsArchCombo {
    param(
        [Parameter(Mandatory = $true)]
        [psobject]$State
    )
    
    $archCombo = $State.Controls.cmbWindowsArch
    if (-not $archCombo) {
        WriteLog "Update-WindowsArchCombo: Architecture ComboBox not found."
        return
    }
    
    $previousSelectedArch = $archCombo.SelectedItem
    
    # Start with a safe, common default
    $availableArchitectures = @('x64') 
    
    $releaseItem = $State.Controls.cmbWindowsRelease.SelectedItem
    $versionItem = $State.Controls.cmbWindowsVersion.SelectedItem
    $skuItem = $State.Controls.cmbWindowsSKU.SelectedItem
    
    if ($null -eq $releaseItem) {
        WriteLog "Update-WindowsArchCombo: No release selected. Defaulting to x64."
        $archCombo.ItemsSource = $availableArchitectures
        $archCombo.SelectedItem = 'x64'
        return
    }
    
    $releaseDisplay = $releaseItem.Display
    $versionValue = if ($null -ne $versionItem) { $versionItem } else { "" }
    $skuValue = if ($null -ne $skuItem) { $skuItem } else { "" }
    
    if ($releaseDisplay -like 'Windows Server*') {
        # All servers are x64 only
        $availableArchitectures = @('x64')
    }
    elseif ($releaseDisplay -like 'Windows 11*') {
        if ($releaseDisplay -like '*LTSC*') {
            # Windows 11 LTSC 2024
            if ($skuValue -like 'IoT*') {
                $availableArchitectures = @('x64', 'arm64')
            }
            else {
                $availableArchitectures = @('x64')
            }
        }
        else {
            # Standard Windows 11
            if ($versionValue -in @('24H2', '25H2')) {
                $availableArchitectures = @('x64', 'arm64')
            }
            else {
                # 22H2, 23H2
                $availableArchitectures = @('x64')
            }
        }
    }
    elseif ($releaseDisplay -like 'Windows 10*') {
        if ($releaseDisplay -like '*LTSB*' -or $releaseDisplay -like '*LTSC*') {
            # Windows 10 LTSB 2016, LTSC 2019, LTSC 2021
            if ($releaseDisplay -like '*2021*' -and $skuValue -like 'IoT*') {
                $availableArchitectures = @('x64', 'arm64')
            }
            else {
                # LTSB 2016, LTSC 2019, LTSC 2021 (non-IoT)
                $availableArchitectures = @('x86', 'x64')
            }
        }
        else {
            # Standard Windows 10 (22H2)
            $availableArchitectures = @('x86', 'x64')
        }
    }
    
    $archCombo.ItemsSource = $availableArchitectures
    
    if ($availableArchitectures -contains $previousSelectedArch) {
        $archCombo.SelectedItem = $previousSelectedArch
    }
    elseif ($availableArchitectures -contains 'x64') {
        $archCombo.SelectedItem = 'x64'
    }
    elseif ($availableArchitectures.Count -gt 0) {
        $archCombo.SelectedIndex = 0
    }
    else {
        $archCombo.SelectedIndex = -1
    }
    WriteLog "Update-WindowsArchCombo: Updated available architectures to ($($availableArchitectures -join ', ')). Selected: $($archCombo.SelectedItem)"
}
    
# Combined function to initialize the Release, Version, and SKU combos
function Get-WindowsSettingsCombos {
    param(
        [string]$isoPath,
        [Parameter(Mandatory = $true)]
        [psobject]$State
    )

    # Determine visibility for download-specific controls based on ISO path
    $visibility = if (-not [string]::IsNullOrEmpty($isoPath) -and $isoPath.EndsWith('.iso', [System.StringComparison]::OrdinalIgnoreCase)) {
        'Collapsed'
    }
    else {
        'Visible'
    }

    # Set visibility for Language and Media Type controls
    $State.Controls.WindowsLangStackPanel.Visibility = $visibility
    $State.Controls.cmbWindowsLang.Visibility = $visibility
    $State.Controls.MediaTypeStackPanel.Visibility = $visibility
    $State.Controls.cmbMediaType.Visibility = $visibility

    # Update Release combo first
    Update-WindowsReleaseCombo -isoPath $isoPath -State $State

    # Get the newly selected release value
    $selectedReleaseValue = 11 # Default to 11 if selection is null
    if ($null -ne $State.Controls.cmbWindowsRelease.SelectedItem) {
        $selectedReleaseValue = $State.Controls.cmbWindowsRelease.SelectedItem.Value
    }

    # Update Version combo based on the selected release
    Update-WindowsVersionCombo -selectedRelease $selectedReleaseValue -isoPath $isoPath -State $State

    # Update SKU combo based on the selected release (now derives values internally)
    Update-WindowsSkuCombo -State $State
    
    # Finally, update the Architecture combo to match the initial state
    Update-WindowsArchCombo -State $State
}

# Dynamic checkboxes for optional features in Windows Settings tab
function UpdateOptionalFeaturesString {
    param(
        [psobject]$State
    )
    $checkedFeatures = @()
    foreach ($entry in $State.Controls.featureCheckBoxes.GetEnumerator()) {
        if ($entry.Value.IsChecked) { $checkedFeatures += $entry.Key }
    }
}
function BuildFeaturesGrid {
    param (
        [Parameter(Mandatory)]
        [System.Windows.FrameworkElement]$parent,
        [Parameter(Mandatory)]
        [array]$allowedFeatures, # Pass the list of features explicitly
        [Parameter(Mandatory = $true)]
        [psobject]$State
    )
    $parent.Children.Clear()
    $State.Controls.featureCheckBoxes.Clear() # Clear the tracking hashtable

    $sortedFeatures = $allowedFeatures | Sort-Object
    $rows = 10 # Define number of rows for layout
    $columns = [math]::Ceiling($sortedFeatures.Count / $rows)

    $featuresGrid = New-Object System.Windows.Controls.Grid
    $featuresGrid.Margin = "0,5,0,5"
    $featuresGrid.ShowGridLines = $false

    # Define grid rows
    for ($r = 0; $r -lt $rows; $r++) {
        $rowDef = New-Object System.Windows.Controls.RowDefinition
        $rowDef.Height = [System.Windows.GridLength]::Auto
        $featuresGrid.RowDefinitions.Add($rowDef) | Out-Null
    }
    # Define grid columns
    for ($c = 0; $c -lt $columns; $c++) {
        $colDef = New-Object System.Windows.Controls.ColumnDefinition
        $colDef.Width = [System.Windows.GridLength]::Auto
        $featuresGrid.ColumnDefinitions.Add($colDef) | Out-Null
    }

    # Populate grid with checkboxes
    for ($i = 0; $i -lt $sortedFeatures.Count; $i++) {
        $featureName = $sortedFeatures[$i]
        $colIndex = [int]([math]::Floor($i / $rows))
        $rowIndex = $i % $rows

        $chk = New-Object System.Windows.Controls.CheckBox
        $chk.Content = $featureName
        $chk.Margin = "5"
        $chk.Add_Checked({
                param($eventSource, $e)
                $window = [System.Windows.Window]::GetWindow($eventSource)
                if ($null -ne $window) {
                    UpdateOptionalFeaturesString -State $window.Tag
                }
            })
        $chk.Add_Unchecked({
                param($eventSource, $e)
                $window = [System.Windows.Window]::GetWindow($eventSource)
                if ($null -ne $window) {
                    UpdateOptionalFeaturesString -State $window.Tag
                }
            })

        $State.Controls.featureCheckBoxes[$featureName] = $chk # Track the checkbox

        [System.Windows.Controls.Grid]::SetRow($chk, $rowIndex)
        [System.Windows.Controls.Grid]::SetColumn($chk, $colIndex)
        $featuresGrid.Children.Add($chk) | Out-Null
    }
    $parent.Children.Add($featuresGrid) | Out-Null
}

# --------------------------------------------------------------------------
# SECTION: Module Export
# --------------------------------------------------------------------------

Export-ModuleMember -Function *