Private/Utilities/Initialize-PIMModules.ps1

function Initialize-PIMModules {
    <#
    .SYNOPSIS
        Initializes required module version metadata for dependency loading.
     
    .DESCRIPTION
        This function handles the initialization of required module version metadata for PIM operations.
        It validates that compatible module versions are available and can remove conflicting loaded
        modules when forced. Import-PIMModule performs the actual module import.
     
    .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'] = '6.0.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."
        $result.Success = $true
        
    }
    catch {
        $result.Success = $false
        $result.Error = $_.Exception.Message
        Write-Error "Failed to initialize PIM modules: $($_.Exception.Message)"
    }
    
    return $result
}