Private/Utilities/Initialize-PIMModules.ps1

function Initialize-PIMModules {
    <#
    .SYNOPSIS
        Initializes and loads required modules with version pinning and just-in-time loading
     
    .DESCRIPTION
        This function handles the initialization of required modules for PIM operations.
        It ensures only the exact required versions are loaded and removes other versions
        from the session to prevent assembly conflicts.
         
        Uses just-in-time loading - modules are only imported when actually needed.
     
    .PARAMETER Force
        Forces reinitialization even if modules are already loaded
         
    .PARAMETER IncludeAzureModules
        Includes Azure PowerShell modules in the initialization process
         
    .OUTPUTS
        PSCustomObject with Success and Error properties
    #>

    [CmdletBinding()]
    param(
        [switch]$Force,
        [switch]$IncludeAzureModules
    )
    
    # Define pinned module versions (working combination)
    $script:RequiredModuleVersions = @{
        'Microsoft.Graph.Authentication'               = '2.29.1'
        'Microsoft.Graph.Users'                        = '2.29.1'
        'Microsoft.Graph.Identity.DirectoryManagement' = '2.29.1'
        'Microsoft.Graph.Identity.Governance'          = '2.29.1'
        'Microsoft.Graph.Groups'                       = '2.29.1'
        'Microsoft.Graph.Identity.SignIns'             = '2.29.1'
    }
    
    # Add Azure modules if requested
    if ($IncludeAzureModules) {
        $script:RequiredModuleVersions['Az.Accounts'] = '5.1.0'
        $script:RequiredModuleVersions['Az.Resources'] = '8.1.0'
    }
    
    # All modules now use minimum version checking for better compatibility
    $script:MinimumVersionModules = @(
        'Microsoft.Graph.Authentication',
        'Microsoft.Graph.Users', 
        'Microsoft.Graph.Identity.DirectoryManagement',
        'Microsoft.Graph.Identity.Governance',
        'Microsoft.Graph.Groups',
        'Microsoft.Graph.Identity.SignIns'
    )
    
    # Add Azure modules to minimum version check if requested
    if ($IncludeAzureModules) {
        $script:MinimumVersionModules += @('Az.Accounts', 'Az.Resources')
    }
    
    $result = [PSCustomObject]@{
        Success       = $true
        Error         = $null
        LoadedModules = @()
    }
    
    try {
        Write-Verbose "Initializing PIM modules with version pinning..."
        if ($IncludeAzureModules) {
            Write-Verbose "Including Azure PowerShell modules in initialization"
        }
        
        # Remove any currently loaded conflicting modules
        if ($Force) {
            Write-Verbose "Force flag specified - removing all loaded Graph and Az modules"
            Remove-ConflictingModules -IncludeAzureModules:$IncludeAzureModules
        }
        
        # Validate required module availability
        # Temporarily suppress verbose output during Get-Module operations
        $currentVerbose = $VerbosePreference
        $VerbosePreference = 'SilentlyContinue'
        
        try {
            foreach ($moduleSpec in $script:RequiredModuleVersions.GetEnumerator()) {
                $moduleName = $moduleSpec.Key
                $requiredVersion = $moduleSpec.Value
                
                # Restore verbose for our own output
                $VerbosePreference = $currentVerbose
                Write-Verbose "Checking availability of $moduleName minimum version $requiredVersion"
                $VerbosePreference = 'SilentlyContinue'
                
                # For all modules, check if we have the required version or higher
                $availableModule = Get-Module -Name $moduleName -ListAvailable | 
                Where-Object { $_.Version -ge [Version]$requiredVersion } |
                Sort-Object Version -Descending |
                Select-Object -First 1
                
                if (-not $availableModule) {
                    $VerbosePreference = $currentVerbose
                    $errorMsg = "Required module $moduleName minimum version $requiredVersion is not installed. Please run: Install-Module -Name $moduleName -MinimumVersion $requiredVersion -Force"
                    Write-Error $errorMsg
                    $result.Success = $false
                    $result.Error = $errorMsg
                    return $result
                }
            }
        }
        finally {
            # Always restore the original verbose preference
            $VerbosePreference = $currentVerbose
        }
        
        # Initialize module loading state tracking
        if (-not $script:ModuleLoadingState) {
            $script:ModuleLoadingState = @{}
        }
        
        Write-Verbose "All required modules are available. Modules will be loaded just-in-time."
        $result.Success = $true
        
    }
    catch {
        $result.Success = $false
        $result.Error = $_.Exception.Message
        Write-Error "Failed to initialize PIM modules: $($_.Exception.Message)"
    }
    
    return $result
}