Public/Save-CIEMConfig.ps1

function Save-CIEMConfig {
    <#
    .SYNOPSIS
        Saves CIEM configuration to config.json and updates the in-memory config.

    .DESCRIPTION
        Writes configuration changes to the config.json file and updates the
        $script:Config variable to ensure both file and memory are in sync.
        This should be called before Connect-CIEM when configuration changes.

    .PARAMETER Config
        The configuration object to save. If not provided, saves $script:Config.

    .PARAMETER Settings
        A hashtable of dot-notation paths and values to update in the config.
        Example: @{ 'azure.authentication.method' = 'ManagedIdentity' }

    .EXAMPLE
        Save-CIEMConfig -Settings @{ 'azure.authentication.method' = 'ManagedIdentity' }

    .EXAMPLE
        $script:Config.azure.authentication.method = 'ServicePrincipalSecret'
        Save-CIEMConfig
    #>

    [CmdletBinding()]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Saves configuration file, no destructive action')]
    param(
        [Parameter()]
        [PSCustomObject]$Config,

        [Parameter()]
        [hashtable]$Settings
    )

    $ErrorActionPreference = 'Stop'

    $configPath = Join-Path -Path $script:ModuleRoot -ChildPath 'config.json'

    # Load current config if not provided
    if (-not $Config) {
        if (Test-Path $configPath) {
            $Config = Get-Content $configPath -Raw | ConvertFrom-Json -AsHashtable
        } else {
            throw "Configuration file not found: $configPath"
        }
    } elseif ($Config -is [PSCustomObject]) {
        # Convert PSCustomObject to hashtable for easier manipulation
        $Config = $Config | ConvertTo-Json -Depth 10 | ConvertFrom-Json -AsHashtable
    }

    # Apply settings if provided
    if ($Settings) {
        foreach ($key in $Settings.Keys) {
            Set-NestedHashtableValue -Hashtable $Config -Path $key -Value $Settings[$key]
        }
    }

    # Save to file
    $jsonContent = $Config | ConvertTo-Json -Depth 10
    Set-Content -Path $configPath -Value $jsonContent -Encoding UTF8

    # Update in-memory config
    $script:Config = Get-Content $configPath -Raw | ConvertFrom-Json

    Write-Verbose "Configuration saved to $configPath"
}

function Set-NestedHashtableValue {
    <#
    .SYNOPSIS
        Sets a value in a nested hashtable using dot notation path.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [hashtable]$Hashtable,

        [Parameter(Mandatory)]
        [string]$Path,

        [Parameter(Mandatory)]
        $Value
    )

    $parts = $Path -split '\.'
    $current = $Hashtable

    for ($i = 0; $i -lt $parts.Count - 1; $i++) {
        $part = $parts[$i]
        if (-not $current.ContainsKey($part)) {
            $current[$part] = @{}
        }
        $current = $current[$part]
    }

    $current[$parts[-1]] = $Value
}