functions/profile/Export-SldgGenerationProfile.ps1

function Export-SldgGenerationProfile {
    <#
    .SYNOPSIS
        Exports the current generation plan and rules to a JSON profile file.

    .DESCRIPTION
        Saves the generation plan configuration including table row counts,
        column semantic types, PII flags, and custom rules to a JSON file.
        This profile can be imported later for consistent data generation.

        Custom rules including AIGenerationHint, CrossColumnDependency, and ValueExamples
        are preserved in the exported profile. ScriptBlock rules are excluded for security.

    .PARAMETER Plan
        The generation plan to export.

    .PARAMETER Path
        The file path to save the JSON profile.

    .PARAMETER IncludeSemanticAnalysis
        If specified, includes the full semantic analysis (types, PII flags) in the export.

    .PARAMETER WhatIf
        Shows what the command would do without actually exporting the profile.

    .PARAMETER Confirm
        Prompts for confirmation before exporting the profile.

    .EXAMPLE
        PS C:\> Export-SldgGenerationProfile -Plan $plan -Path 'C:\profiles\mydb.json'

        Exports the plan to a JSON file.
    #>

    [OutputType([void])]
    [CmdletBinding(SupportsShouldProcess)]
    param (
        [Parameter(Mandatory, ValueFromPipeline)]
        [SqlLabDataGenerator.GenerationPlan]$Plan,

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

        [switch]$IncludeSemanticAnalysis
    )

    process {
    # Resolve and normalize path — reject path traversal attempts that escape working directory
    if ($Path -match '(?:^|[\\/])\.\.(?:[\\/]|$)') {
        Stop-PSFFunction -String 'Profile.ExportPathInvalid' -StringValues $Path -EnableException $true
    }
    $resolvedPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
    $Path = [System.IO.Path]::GetFullPath($resolvedPath)

    if (-not $PSCmdlet.ShouldProcess($Path, 'Export generation profile')) { return }

    Write-PSFMessage -Level Host -Message ($script:strings.'Profile.Exporting' -f $Path)

    $export = @{
        database         = $Plan.Database
        mode             = $Plan.Mode
        useAIGeneration  = $Plan.UseAIGeneration
        createdAt        = (Get-Date -Format 'o')
        tables           = @{}
    }

    foreach ($tablePlan in $Plan.Tables) {
        $tableExport = @{
            rowCount = $tablePlan.RowCount
            order    = $tablePlan.Order
            columns  = @{}
        }

        foreach ($colPlan in $tablePlan.Columns) {
            if ($colPlan.Skip) { continue }

            $colExport = @{
                dataType     = $colPlan.DataType
                semanticType = $colPlan.SemanticType
                generator    = $colPlan.Generator
            }

            if ($IncludeSemanticAnalysis) {
                $colExport['isPII'] = $colPlan.IsPII
            }

            if ($colPlan.ForeignKey) {
                $colExport['foreignKey'] = @{
                    referencedTable  = "$($colPlan.ForeignKey.ReferencedSchema).$($colPlan.ForeignKey.ReferencedTable)"
                    referencedColumn = $colPlan.ForeignKey.ReferencedColumn
                }
            }

            # Include custom rules
            if ($colPlan.CustomRule) {
                if ($colPlan.CustomRule.ContainsKey('ValueList')) {
                    $colExport['valueList'] = $colPlan.CustomRule.ValueList
                }
                if ($colPlan.CustomRule.ContainsKey('StaticValue')) {
                    $colExport['staticValue'] = $colPlan.CustomRule.StaticValue
                }
                if ($colPlan.CustomRule.ContainsKey('Generator')) {
                    $colExport['generator'] = $colPlan.CustomRule.Generator
                }
                if ($colPlan.CustomRule.ContainsKey('AIGenerationHint')) {
                    $colExport['aiGenerationHint'] = $colPlan.CustomRule.AIGenerationHint
                }
                if ($colPlan.CustomRule.ContainsKey('CrossColumnDependency')) {
                    $colExport['crossColumnDependency'] = $colPlan.CustomRule.CrossColumnDependency
                }
                if ($colPlan.CustomRule.ContainsKey('ValueExamples')) {
                    $colExport['valueExamples'] = $colPlan.CustomRule.ValueExamples
                }
            }

            $tableExport.columns[$colPlan.ColumnName] = $colExport
        }

        $export.tables[$tablePlan.FullName] = $tableExport
    }

    $parentDir = Split-Path -Path $Path -Parent
    if ($parentDir -and -not (Test-Path $parentDir)) {
        $null = New-Item -Path $parentDir -ItemType Directory -Force
    }

    $export | ConvertTo-Json -Depth 10 | Set-Content -Path $Path -Encoding UTF8

    Write-PSFMessage -Level Host -Message ($script:strings.'Profile.Exported' -f $Path)
    }
}