source/Public/Show-RJInteractiveSetup.ps1

function Show-RJInteractiveSetup {
    <#
    .SYNOPSIS
    Launches an interactive menu-driven setup for configuring RealmJoin tenant.
 
    .DESCRIPTION
    This cmdlet provides an interactive menu system for configuring RealmJoin tenant settings.
    It guides users through:
    - Choosing between New Tenant Setup or Update Existing Tenant
    - Selecting optional features with detailed descriptions
    - Choosing permission mode (Full or Read-Only)
    - Reviewing and confirming selections
    - Executing the configuration
 
    The menu system uses arrow keys for navigation and provides clear visual feedback.
 
    .PARAMETER SkipBanner
    Skips the welcome banner display.
 
    .EXAMPLE
    Show-RJInteractiveSetup
    Launches the interactive setup wizard.
 
    .EXAMPLE
    Show-RJInteractiveSetup -SkipBanner
    Launches the interactive setup wizard without the banner.
 
    .NOTES
    This cmdlet requires appropriate Azure AD permissions to create service principals and assign app roles.
    #>


    [CmdletBinding()]
    param(
        [switch]$SkipBanner
    )

    begin {
        # Check for PowerShell ISE compatibility
        if (Test-PowerShellISE) {
            Write-Warning "PowerShell ISE is not supported for interactive menus."
            Write-Host ""
            Write-Host "Please use one of the following alternatives:" -ForegroundColor White
            Write-Host " • Windows PowerShell Console (powershell.exe)" -ForegroundColor Green
            Write-Host " • PowerShell Core (pwsh.exe)" -ForegroundColor Green
            Write-Host " • Windows Terminal with PowerShell" -ForegroundColor Green
            Write-Host " • Visual Studio Code with PowerShell Extension" -ForegroundColor Green
            Write-Host ""
            Write-Host "You can also use the individual cmdlets directly:" -ForegroundColor White
            Write-Host " • New-RJTenant" -ForegroundColor Green
            Write-Host " • Update-RJTenant" -ForegroundColor Green
            Write-Host " • Get-RJCurrentConfiguration" -ForegroundColor Green
            Write-Host ""
            $script:SkipExecution = $true
            return
        }

        $script:SkipExecution = $false

        # Initialize required modules
        Write-Host "Initializing modules..." -ForegroundColor Gray
        if (-not (Initialize-RequiredModule)) {
            Write-Host "ERROR: Module initialization failed" -ForegroundColor Red
            return
        }
        Write-Host ""
    }

    process {
        # Skip execution if we're in an unsupported environment
        if ($script:SkipExecution) {
            return
        }

        # Display welcome banner
        if (-not $SkipBanner) {
            Show-RJInteractiveBanner
        }

        # Main menu loop
        $continue = $true
        while ($continue) {
            $mainMenuChoice = Show-RJMainMenu

            switch ($mainMenuChoice) {
                'NewTenant' {
                    Show-RJInteractiveNewTenant
                }
                'UpdateTenant' {
                    Show-RJInteractiveUpdateTenant
                }
                'ShowFeatures' {
                    Show-RJFeatureInfo
                    Write-Host "`nPress any key to continue..." -ForegroundColor Gray
                    $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
                }
                'Exit' {
                    Write-Host ""
                    $continue = $false
                }
            }
        }
    }

    end {
        Write-Verbose "Interactive setup completed"
    }
}

function Show-RJInteractiveBanner {
    Clear-Host
    Write-Host "RealmJoin Tenant Configuration v1.1.0" -ForegroundColor White
    Write-Host ("-" * 50) -ForegroundColor DarkGray
    Write-Host ""
}

function Show-RJMainMenu {
    $extraInstructions = @(
        "Option 1 creates new configuration with review before applying.",
        "Option 2 shows current state and allows targeted modifications."
    )

    return Show-RJGenericMenu -Title "RealmJoin Configuration" -Prompt "Select an option:" -Options $MainMenuOptions -ExtraInstructions $extraInstructions
}

function Show-RJTenantAuthentication {

    Write-Host "Authenticating..." -ForegroundColor Gray

    try {
        $null = Invoke-RJOperationWithRetry -Operation {
            Invoke-GraphLogin
        } -OperationName "Microsoft Graph Authentication" -ShowProgress

        $tenantInfo = Invoke-RJOperationWithRetry -Operation {
            Get-TenantInfo
        } -OperationName "Retrieve Tenant Information"

        Write-Host "Connected: $($tenantInfo.DisplayName)" -ForegroundColor Green
        Write-Host "Tenant ID: $($tenantInfo.TenantId)" -ForegroundColor DarkGray
        Write-Host ""

        return $tenantInfo
    }
    catch {
        Write-Host "Authentication failed: $_" -ForegroundColor Red
        Write-Host "Press any key to return to main menu..." -ForegroundColor Gray
        $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
        return $null
    }
}

function Show-RJInteractiveNewTenant {
    Clear-Host
    Write-Host "New Tenant Setup" -ForegroundColor White
    Write-Host ("-" * 50) -ForegroundColor DarkGray
    Write-Host ""

    # Step 1: Login with error handling
    $tenantInfo = Show-RJTenantAuthentication

    if ($null -eq $tenantInfo) {
        return
    }

    # Step 2: Check if tenant is already configured
    Write-Host "Checking tenant configuration..." -ForegroundColor Gray

    $isConfigured = Test-RJTenantAlreadyConfigured

    if ($isConfigured) {
        Write-Host "NOTICE: This tenant appears to already have RealmJoin configuration." -ForegroundColor Yellow
        Write-Host ""

        $choice = Show-RJGenericMenu -Title "Tenant Already Configured" -Prompt "This tenant appears to already have RealmJoin configuration.`nWhat would you like to do?" -Options $TenantConfiguredOptions -AllowEscape

        switch ($choice) {
            'UpdateTenant' {
                Show-RJInteractiveUpdateTenant
                return
            }
            'MainMenu' {
                return
            }
            { $null -eq $_ } {
                return
            }
        }
    }

    # Step 3: Select permission mode
    Write-Host "Permission Mode" -ForegroundColor Gray

    $permissionMode = Show-RJGenericMenu -Title "Permission Mode" -Prompt "Select permission mode:" -Options $PermissionModeOptions -AllowEscape

    if ($null -eq $permissionMode) {
        return
    }

    # Step 4: Select features
    Write-Host "`nFeature Selection" -ForegroundColor Gray

    $allFeatures = Get-RJFeatureDefinitionList
    $optionalFeatures = $allFeatures | Where-Object { -not $_.IsMandatory }
    $mandatoryFeatures = $allFeatures | Where-Object { $_.IsMandatory }

    $promptText = "Mandatory Features:`n"
    foreach ($feature in $mandatoryFeatures) {
        $promptText += " * $($feature.Name) - $($feature.Description)`n"
    }
    $promptText += "`nOptional Features:"

    $selectedFeatures = Show-RJGenericMultiSelectMenu -Title "Feature Selection" -Prompt $promptText -Items $optionalFeatures -DefaultSelected $DefaultSelectedFeatures

    if ($null -eq $selectedFeatures) {
        return
    }

    # Step 5: Review and confirm
    Write-Host "`nPlease wait..." -ForegroundColor Gray

    # Show analysis using existing function
    $allSelectedFeatures = @($mandatoryFeatures.Name) + @($selectedFeatures)
    $analysisResult = Get-RJTenantPermissionAnalysis -FeatureResolution (Resolve-RJFeature -SelectedFeatures $allSelectedFeatures -ReadOnly:($permissionMode -eq 'ReadOnly'))

    Clear-Host
    Write-Host "Configuration Review" -ForegroundColor White
    Write-Host ("=" * 60) -ForegroundColor DarkGray
    Write-Host ""
    Write-Host "Tenant: $($tenantInfo.DisplayName)" -ForegroundColor Green
    Write-Host "ID: $($tenantInfo.TenantId)" -ForegroundColor DarkGray
    Write-Host "Permission Mode: $(if ($permissionMode -eq 'ReadOnly') { 'Read-Only' } else { 'Read/Write' })" -ForegroundColor Green
    Write-Host ""

    Show-RJFeatureAnalysis -FeatureAnalysis $analysisResult.FeatureAnalysis -OrphanedServicePrincipals $analysisResult.OrphanedServicePrincipals

    $confirm = Show-RJConfirmationMenu -Message "Proceed with configuration?"

    if (-not $confirm) {
        return
    }

    Write-Host ""
    Write-Host "Applying configuration..." -ForegroundColor Gray
    Write-Host ""

    try {
        Invoke-RJOperationWithRetry -Operation {
            if ($permissionMode -eq 'ReadOnly') {
                New-RJTenant -Features $selectedFeatures -ReadOnly
            }
            else {
                New-RJTenant -Features $selectedFeatures
            }
        } -OperationName "Apply Configuration" -ShowProgress

        Write-Host ""
        Write-Host "Configuration completed successfully." -ForegroundColor Green
    }
    catch {
        Write-Host ""
        Write-Host "ERROR: $_" -ForegroundColor Red
        Write-Host ""
        Write-Host "New tenant setup failed. You can retry the setup process." -ForegroundColor Yellow
    }

    Write-Host ""
    Write-Host "Press any key to continue..." -ForegroundColor Gray
    $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
}

function Show-RJInteractiveUpdateTenant {
    Clear-Host
    Write-Host "Modify Existing Configuration" -ForegroundColor White
    Write-Host ("-" * 50) -ForegroundColor DarkGray
    Write-Host ""

    # Step 1: Login with error handling
    $tenantInfo = Show-RJTenantAuthentication

    if ($null -eq $tenantInfo) {
        return
    }

    # Step 2: Analyze current configuration with error handling
    Write-Host "Analyzing current configuration..." -ForegroundColor Gray
    try {
        $currentConfig = Invoke-RJOperationWithRetry -Operation {
            Get-RJCurrentConfiguration
        } -OperationName "Analyze Configuration" -ShowProgress


        if ($currentConfig.ConfiguredFeatures.Count -eq 0 -and $currentConfig.LegacyApplications.Count -eq 0) {
            Clear-Host
            Write-Host "No existing RealmJoin configuration found." -ForegroundColor Yellow
            Write-Host "Use 'New Tenant Setup' option instead." -ForegroundColor Yellow
            Write-Host ""
            Write-Host "Press any key to continue..." -ForegroundColor Gray
            $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
            return
        }

        Show-RJCurrentConfiguration -Configuration $currentConfig

        Write-Host "Press any key to continue..." -ForegroundColor Gray
        $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

        $updateOptions = $UpdateMenuOptions.Clone()

        if ($currentConfig.LegacyApplications.Count -gt 0) {
            $legacyOption = [PSCustomObject]@{
                Key         = 'RemoveLegacy'
                Display     = "[4] Remove Legacy Applications ($($currentConfig.LegacyApplications.Count) found)"
                Description = 'Clean up old RealmJoin apps'
            }
            $updateOptions = $updateOptions[0..2] + $legacyOption
        }

        $updateChoice = Show-RJGenericMenu -Title "Update Options" -Prompt "What would you like to update?" -Options $updateOptions -AllowEscape

        switch ($updateChoice) {
            'AddFeatures' {
                $allFeatureDefinitions = Get-RJFeatureDefinitionList
                Show-RJUpdateTenantAddFeature -CurrentConfig $currentConfig -AllFeatureDefinitions $allFeatureDefinitions
            }
            'RemoveFeatures' {
                $allFeatureDefinitions = Get-RJFeatureDefinitionList
                Show-RJUpdateTenantRemoveFeature -CurrentConfig $currentConfig -AllFeatureDefinitions $allFeatureDefinitions
            }
            'ChangePermissions' {
                Show-RJUpdateTenantChangePermission -CurrentConfig $currentConfig
            }
            'RemoveLegacy' {
                Show-RJUpdateTenantRemoveLegacy -CurrentConfig $currentConfig
            }
            { $null -eq $_ } {
                return
            }
        }
    }
    catch {
        Write-Host ""
        Write-Host "ERROR: $_" -ForegroundColor Red
    }

    Write-Host ""
    Write-Host "Press any key to continue..." -ForegroundColor Gray
    $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
}

function Show-RJConfirmationMenu {
    param(
        [string]$Message = "Do you want to proceed?"
    )

    Write-Host ""
    Write-Host ("=" * 60) -ForegroundColor DarkGray
    Write-Host ""
    Write-Host $Message -ForegroundColor White
    Write-Host ""
    Write-Host "[Y] Yes [N] No (return to main menu)" -ForegroundColor DarkGray
    Write-Host ""
    Write-Host "Your choice: " -ForegroundColor White -NoNewline

    # Handle user input
    while ($true) {
        $key = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

        switch ($key.Character.ToString().ToUpper()) {
            'Y' {
                Write-Host "Yes" -ForegroundColor Green
                return $true
            }
            'N' {
                Write-Host "No" -ForegroundColor Red
                return $false
            }
        }
    }
}

function Show-RJUpdateTenantAddFeature {
    param(
        [Parameter(Mandatory)]
        $CurrentConfig,

        [Parameter(Mandatory)]
        $AllFeatureDefinitions
    )

    $configuredNames = $CurrentConfig.ConfiguredFeatures.Name
    $availableFeatures = $AllFeatureDefinitions | Where-Object {
        $_.Name -notin $configuredNames -and -not $_.IsMandatory
    }

    if ($availableFeatures.Count -eq 0) {
        Clear-Host
        Write-Host "All available features are already configured." -ForegroundColor Yellow
        return
    }

    $featuresToAdd = Show-RJGenericMultiSelectMenu -Title "Add Features" -Prompt "Select features to add:" -Items $availableFeatures

    if ($null -eq $featuresToAdd) {
        return
    }

    # Add mandatory features that are not already configured
    $mandatoryFeatures = $AllFeatureDefinitions | Where-Object { $_.IsMandatory -and $_.Name -notin $configuredNames }
    if ($mandatoryFeatures) {
        $featuresToAdd = @($featuresToAdd) + @($mandatoryFeatures.Name)
    }

    if ($featuresToAdd -and $featuresToAdd.Count -gt 0) {
        $permissionMode = Show-RJGenericMenu -Title "Permission Mode" -Prompt "Select permission mode for adding features:" -Options $PermissionModeOptions -AllowEscape

        if ($null -eq $permissionMode) {
            return
        }
        Write-Host "`nPlease wait..." -ForegroundColor Gray

        # Show analysis for features to add using incremental parameters
        $analysisResult = Get-RJTenantPermissionAnalysis -FeatureResolution (Resolve-RJFeature -CurrentConfig $CurrentConfig -FeaturesToAdd $featuresToAdd -ReadOnly:($permissionMode -eq 'ReadOnly'))

        Clear-Host
        Write-Host "Add Features Review" -ForegroundColor White
        Write-Host ("=" * 60) -ForegroundColor DarkGray
        Write-Host ""
        Write-Host "Permission Mode: $(if ($permissionMode -eq 'ReadOnly') { 'Read-Only' } else { 'Read/Write' })" -ForegroundColor Green
        Write-Host ""

        # Show only the features being added
        $addedFeatureAnalysis = $analysisResult.FeatureAnalysis | Where-Object { $_.FeatureName -in $featuresToAdd }
        Show-RJFeatureAnalysis -FeatureAnalysis $addedFeatureAnalysis -OrphanedServicePrincipals @()

        $confirm = Show-RJConfirmationMenu -Message "Proceed with adding features?"

        if (-not $confirm) {
            return
        }

        Write-Host ""
        Write-Host "Adding selected features..." -ForegroundColor Gray

        try {
            Invoke-RJOperationWithRetry -Operation {
                if ($permissionMode -eq 'ReadOnly') {
                    Update-RJTenant -AddFeatures $featuresToAdd -ReadOnly
                }
                else {
                    Update-RJTenant -AddFeatures $featuresToAdd
                }
            } -OperationName "Add Features" -ShowProgress

            Write-Host ""
            Write-Host "Features added successfully." -ForegroundColor Green
        }
        catch {
            Write-Host ""
            Write-Host "ERROR: $_" -ForegroundColor Red
        }
    }
}

function Show-RJUpdateTenantRemoveFeature {
    param(
        [Parameter(Mandatory)]
        $CurrentConfig,

        [Parameter(Mandatory)]
        $AllFeatureDefinitions
    )

    $removableConfiguredFeatures = $CurrentConfig.ConfiguredFeatures | Where-Object { -not $_.IsMandatory }

    if ($removableConfiguredFeatures.Count -eq 0) {
        Clear-Host
        Write-Host "Remove Features" -ForegroundColor White
        Write-Host ("-" * 50) -ForegroundColor DarkGray
        Write-Host ""
        Write-Host "No removable features found." -ForegroundColor Yellow
        Write-Host "Only optional features can be removed." -ForegroundColor Gray
        return
    }

    $removableFeatures = $AllFeatureDefinitions | Where-Object {
        $_.Name -in $removableConfiguredFeatures.Name
    }

    $selectedFeatures = Show-RJGenericMultiSelectMenu -Title "Remove Features" -Prompt "Select features to remove:`n`nWARNING: Removing features cannot be easily undone" -Items $removableFeatures -SelectedColor "Red"

    if ($null -eq $selectedFeatures) {
        return
    }

    if ($selectedFeatures -and $selectedFeatures.Count -gt 0) {
        Write-Host "Analyzing removal impact..." -ForegroundColor Gray

        $removalAnalysis = Get-RJTenantPermissionAnalysis -FeatureResolution (Resolve-RJFeature -CurrentConfig $CurrentConfig -FeaturesToRemove $selectedFeatures)
        $removalAnalysisToShow = $removalAnalysis.FeatureAnalysis | Where-Object { $_.FeatureName -in $selectedFeatures }
        Show-RJFeatureAnalysis -FeatureAnalysis $removalAnalysisToShow -OrphanedServicePrincipals $removalAnalysis.OrphanedServicePrincipals

        Write-Host "Press any key to continue..." -ForegroundColor Gray
        $null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")

        Write-Host ""
        Write-Host "WARNING: Removing features cannot be easily undone" -ForegroundColor Red

        $confirm = Show-RJConfirmationMenu -Message "Proceed with removing selected features?"

        if (-not $confirm) {
            return
        }

        Write-Host ""
        Write-Host "Removing selected features..." -ForegroundColor Gray

        try {
            $currentPermissionMode = if ($CurrentConfig.ConfiguredFeatures | Where-Object { $_.PermissionMode -eq 'ReadOnly' }) { 'ReadOnly' } else { 'Full' }

            Invoke-RJOperationWithRetry -Operation {
                if ($currentPermissionMode -eq 'ReadOnly') {
                    Update-RJTenant -RemoveFeatures $selectedFeatures -ReadOnly
                }
                else {
                    Update-RJTenant -RemoveFeatures $selectedFeatures
                }
            } -OperationName "Remove Features" -ShowProgress

            Write-Host ""
            Write-Host "Features removed successfully:" -ForegroundColor Green
            foreach ($feature in $selectedFeatures) {
                Write-Host " * $feature" -ForegroundColor Green
            }
        }
        catch {
            Write-Host ""
            Write-Host "ERROR: $_" -ForegroundColor Red
        }
    }
}

function Show-RJUpdateTenantChangePermission {
    param(
        [Parameter(Mandatory)]
        $CurrentConfig
    )

    $newPermissionMode = Show-RJGenericMenu -Title "Permission Mode" -Prompt "Select new permission mode:" -Options $PermissionModeOptions -AllowEscape

    if ($null -eq $newPermissionMode) {
        return
    }
    Write-Host "`nPlease wait..." -ForegroundColor Gray

    $allCurrentFeatures = $CurrentConfig.ConfiguredFeatures | ForEach-Object { $_.Name }

    $analysisResult = Get-RJTenantPermissionAnalysis -FeatureResolution (Resolve-RJFeature -CurrentConfig $CurrentConfig -SelectedFeatures $allCurrentFeatures -ReadOnly:($newPermissionMode -eq 'ReadOnly'))

    # Check if there are any actual changes to be made
    $hasChanges = $analysisResult.FeatureAnalysis | Where-Object { $_.FeatureChangeType -ne "NoChanges" }

    if (-not $hasChanges) {
        Write-Host ""
        Write-Host "No permission changes are required. The tenant is already configured with the selected permission mode." -ForegroundColor Yellow
        return
    }

    Show-RJFeatureAnalysis -FeatureAnalysis $analysisResult.FeatureAnalysis -OrphanedServicePrincipals $removalAnalysis.OrphanedServicePrincipals

    $confirm = Show-RJConfirmationMenu -Message "Proceed with permission changes?"

    if (-not $confirm) {
        return
    }

    Write-Host ""
    Write-Host "Updating permissions..." -ForegroundColor Gray
    Write-Host ""

    if ($newPermissionMode -eq 'ReadOnly') {
        Update-RJTenant -Features $allCurrentFeatures -ReadOnly
    }
    else {
        Update-RJTenant -Features $allCurrentFeatures
    }

    Write-Host ""
    Write-Host "Permissions updated successfully." -ForegroundColor Green

}

function Show-RJUpdateTenantRemoveLegacy {
    param(
        [Parameter(Mandatory)]
        $CurrentConfig
    )

    Clear-Host
    Write-Host "Remove Legacy Applications" -ForegroundColor White
    Write-Host ("=" * 60) -ForegroundColor DarkGray
    Write-Host ""
    Write-Host "Legacy applications to remove:" -ForegroundColor Yellow
    Write-Host ""
    foreach ($app in $CurrentConfig.LegacyApplications) {
        Write-Host " * $($app.DisplayName)" -ForegroundColor Gray
    }

    $confirm = Show-RJConfirmationMenu -Message "Proceed with removing legacy applications?"

    if (-not $confirm) {
        return
    }

    Write-Host ""
    Write-Host "Removing legacy applications..." -ForegroundColor Gray
    $results = Remove-RJLegacyApplication
    if ($results.Success) {
        Write-Host ""
        Write-Host "Legacy applications removed successfully." -ForegroundColor Green
    }
    else {
        Write-Host ""
        Write-Host "Some legacy applications could not be removed." -ForegroundColor Yellow
    }
}