Public/New-PstScript.ps1

function New-PstScript {
    <#
.SYNOPSIS
    Creates a new script file from a template or using intelligent code generation.
.DESCRIPTION
    This function takes a name parameter and creates a new PowerShell script based on the
    specified complexity level. It supports two modes:

    1. Template Mode (default): Copies a script template
    2. Generator Mode (-UseGenerator): Uses the intelligent code generation system to create
       customized scripts with proper structure based on complexity level

    Complexity Levels:
    - Basic: Simple script with minimal structure (no CmdletBinding, simple execution)
    - Standard: Script with CmdletBinding, parameter validation, and error handling
    - Advanced: Full script features including ShouldProcess, comprehensive error handling

    Legacy ComplexityLevel values (Basic, Moderate, Complex) are automatically mapped to the new system.
.PARAMETER Name
    (Required) The name for the new script file.
.PARAMETER Complexity
    (Optional) The complexity level for code generation. Valid values: Basic, Standard, Advanced.
    Defaults to Standard. Only used with -UseGenerator switch.
.PARAMETER ComplexityLevel
    (Optional) Legacy parameter for template mode. Valid values: Basic, Moderate, Complex.
    Defaults to Moderate for backward compatibility. Ignored when -UseGenerator is specified.
.PARAMETER Parameters
    (Optional) Array of parameter definitions for the generated script. Each can be:
    - A string (parameter name, defaults to [string] type)
    - A hashtable with Name, Type, Mandatory, Pipeline, DefaultValue, etc.
    Only used with -UseGenerator switch.
.PARAMETER Synopsis
    (Optional) Brief description for the script's help. Only used with -UseGenerator.
.PARAMETER UseGenerator
    (Optional) Switch to use the intelligent code generation system instead of templates.
.PARAMETER Force
    (Optional) Forces creation even if file exists, useful in automation scenarios.
.PARAMETER IncludeProjectLayout
    (Optional) Creates a complete project structure including src/, tests/, docs/ directories.
.EXAMPLE
    New-PstScript -Name MyScript
    Creates a new script using the Moderate template (legacy mode).
.EXAMPLE
    New-PstScript -Name DataProcessor -UseGenerator -Complexity Standard
    Creates a Standard complexity script using the intelligent code generator.
.EXAMPLE
    New-PstScript -Name BatchJob -UseGenerator -Complexity Advanced -Parameters @('InputPath', 'OutputPath')
    Creates an Advanced script with custom parameters using the code generator.
.NOTES
    Template mode requires template files in Resources/Samples directory.
    Generator mode uses the new complexity schema system for dynamic code creation.
.LINK
    https://docs.microsoft.com/en-us/powershell/scripting/overview
#>

    [CmdletBinding(SupportsShouldProcess)]
    param (
        [Parameter(Mandatory = $true, Position = 0,
            HelpMessage = "The name for the new script file.")]
        [ValidatePattern('^[A-Za-z][A-Za-z0-9\-_]*$')]
        [string]$Name,

        [Parameter(Mandatory = $false,
            HelpMessage = "Complexity level for code generation (Basic, Standard, Advanced).")]
        [ValidateSet("Basic", "Standard", "Advanced")]
        [string]$Complexity = "Standard",

        [Parameter(Mandatory = $false,
            HelpMessage = "Legacy complexity level for template mode.")]
        [ValidateSet("Basic", "Moderate", "Complex")]
        [string]$ComplexityLevel = "Moderate",

        [Parameter(Mandatory = $false,
            HelpMessage = "Parameter definitions for the generated script.")]
        [object[]]$Parameters = @(),

        [Parameter(Mandatory = $false,
            HelpMessage = "Brief description for the script's help.")]
        [string]$Synopsis,

        [Parameter(Mandatory = $false,
            HelpMessage = "Use the intelligent code generation system instead of templates.")]
        [switch]$UseGenerator,

        [Parameter(Mandatory = $false)]
        [switch]$Force,

        [Parameter(Mandatory = $false)]
        [switch]$IncludeProjectLayout
    )
    begin {
        Write-Debug -Message "Begin '$($MyInvocation.MyCommand.Name)' at '$(Get-Date)'"

        # Determine file path based on project layout option
        if ($IncludeProjectLayout) {
            $projectRoot = $Name
            $newFilePath = Join-Path $projectRoot "src" "$Name.ps1"
        } else {
            $newFilePath = "$Name.ps1"
        }

        if ($UseGenerator) {
            # Using new code generation system
            Write-Verbose "Using intelligent code generation with complexity: $Complexity"
        } else {
            # Using legacy template mode
            # Select template based on complexity level
            $templateFileName = switch ($ComplexityLevel) {
                "Basic"     { "Script-Basic.ps1" }
                "Moderate"  { "Script-Moderate.ps1" }
                "Complex"   { "Script-Complex.ps1" }
                default     { "Script-Moderate.ps1" }  # Fallback to Moderate
            }

            $templatePath = $Samples[$templateFileName]

            Write-Verbose "Using template mode with complexity level: $ComplexityLevel"
            Write-Verbose "Selected template: $templateFileName"

            if (-not $templatePath) {
                throw "Template '$templateFileName' not found in Samples hashtable. Available templates: $($Samples.Keys -join ', ')"
            }
            if (-not (Test-Path $templatePath)) {
                throw "Template file not found: $templatePath"
            } else {
                Write-Verbose "Template file found: $templatePath"
            }
        }
    }
    process {
        try {
            # Check if we're in automation mode - inline check to avoid scope issues
            $isAutomationMode = $Force -or
            ($Global:PstAutomationMode -eq $true) -or
            ($env:CI -eq 'true') -or
            ($env:GITHUB_ACTIONS -eq 'true') -or
            ($Host.Name -eq 'ServerRemoteHost') -or
            (-not [Environment]::UserInteractive) -or
            ($global:ConfirmPreference -eq 'None')

            # Create project structure if IncludeProjectLayout is specified
            if ($IncludeProjectLayout) {
                $projectRoot = $Name

                # Create directory structure
                $directories = @(
                    $projectRoot,
                    (Join-Path $projectRoot "src"),
                    (Join-Path $projectRoot "tests"),
                    (Join-Path $projectRoot "tests" "Unit"),
                    (Join-Path $projectRoot "tests" "Integration"),
                    (Join-Path $projectRoot "docs")
                )

                foreach ($dir in $directories) {
                    if (-not (Test-Path $dir)) {
                        if ($isAutomationMode -or $PSCmdlet.ShouldProcess($dir, "Create directory")) {
                            New-Item -Path $dir -ItemType Directory -Force | Out-Null
                            Write-Verbose "Created directory: $dir"
                        }
                    }
                }

                # Create README.md in root
                $readmeContent = @"
# $Name

PowerShell script for [brief description].

## Installation

``````powershell
.\src\$Name.ps1
``````

## Usage

``````powershell
.\src\$Name.ps1 -Parameter Value
``````

## Testing

``````powershell
Invoke-Pester -Path .\tests\
``````

## License

[Specify license]
"@

                $readmePath = Join-Path $projectRoot "README.md"
                if ($isAutomationMode -or $PSCmdlet.ShouldProcess($readmePath, "Create README.md")) {
                    $readmeContent | Set-Content -Path $readmePath
                    Write-Verbose "Created: $readmePath"
                }

                # Create .gitignore
                $gitignoreContent = @"
# Build artifacts
build/
*.nupkg

# Test results
TestResults*.xml
coverage*.xml

# Temporary files
temp/
*.tmp
*.log
"@

                $gitignorePath = Join-Path $projectRoot ".gitignore"
                if ($isAutomationMode -or $PSCmdlet.ShouldProcess($gitignorePath, "Create .gitignore")) {
                    $gitignoreContent | Set-Content -Path $gitignorePath
                    Write-Verbose "Created: $gitignorePath"
                }

                # Create docs README.md
                $docsReadmeContent = @"
# $Name Documentation

## Overview

[Script overview and purpose]

## Parameters

[Parameter documentation]

## Examples

[Usage examples]

## Notes

[Additional notes]
"@

                $docsReadmePath = Join-Path $projectRoot "docs" "README.md"
                if ($isAutomationMode -or $PSCmdlet.ShouldProcess($docsReadmePath, "Create docs README.md")) {
                    $docsReadmeContent | Set-Content -Path $docsReadmePath
                    Write-Verbose "Created: $docsReadmePath"
                }

                # Create test file
                $testContent = @"
BeforeAll {
    `$scriptPath = "`$PSScriptRoot\..\..\src\$Name.ps1"
}

Describe "$Name" {
    Context "When executed with valid parameters" {
        It "Should execute without errors" {
            # Arrange

            # Act

            # Assert
            `$true | Should -Be `$true
        }
    }

    Context "When executed with invalid parameters" {
        It "Should handle errors gracefully" {
            # Arrange & Act & Assert
            `$true | Should -Be `$true
        }
    }
}
"@

                $testFilePath = Join-Path $projectRoot "tests" "Unit" "$Name.Tests.ps1"
                if ($isAutomationMode -or $PSCmdlet.ShouldProcess($testFilePath, "Create test file")) {
                    $testContent | Set-Content -Path $testFilePath
                    Write-Verbose "Created: $testFilePath"
                }
            }

            # Check if file already exists
            if ((Test-Path $newFilePath) -and -not $isAutomationMode) {
                if (-not $PSCmdlet.ShouldProcess($newFilePath, "Overwrite existing script file")) {
                    Write-Warning "Operation cancelled by user."
                    return
                }
            }
            elseif ((Test-Path $newFilePath) -and $isAutomationMode -and -not $Force) {
                Write-Warning "File '$newFilePath' already exists. Use -Force to overwrite in automation mode."
                return
            }

            # Proceed with file creation - skip ShouldProcess in automation mode
            if ($isAutomationMode -or $PSCmdlet.ShouldProcess($newFilePath, "Create new script file")) {
                # Create parent directory if it doesn't exist (for project layout)
                $parentDir = Split-Path -Path $newFilePath -Parent
                if ($parentDir -and -not (Test-Path $parentDir)) {
                    New-Item -Path $parentDir -ItemType Directory -Force | Out-Null
                }

                if ($UseGenerator) {
                    # Use intelligent code generation
                    Write-Verbose "Generating script code with complexity: $Complexity"

                    $generatorParams = @{
                        FunctionName = $Name
                        Type = 'Script'
                        Complexity = $Complexity
                    }

                    if ($Parameters.Count -gt 0) {
                        $generatorParams.Parameters = $Parameters
                    }

                    if ($Synopsis) {
                        $generatorParams.Synopsis = $Synopsis
                    }

                    $newContent = New-PstGeneratedCode @generatorParams
                } else {
                    # Use template mode
                    Write-Information -Message "Copy-Item -Path '$($templatePath)' -Destination '$(Join-Path (Get-Location) $newFilePath)'"
                    Copy-Item -Path $templatePath -Destination $newFilePath
                    $newContent = $null  # Content already copied
                }

                # Write content if generated (template mode uses Copy-Item)
                if ($newContent) {
                    $newContent | Set-Content -Path $newFilePath
                }

                if ($IncludeProjectLayout) {
                    Write-Output "New script project created: $projectRoot"
                    Write-Output " - Script file: $newFilePath"
                    Write-Output " - Test file: tests\Unit\$Name.Tests.ps1"
                    Write-Output " - Documentation: docs\README.md"
                    if ($UseGenerator) {
                        Write-Output " - Generated with: $Complexity complexity"
                    }
                } else {
                    if ($UseGenerator) {
                        Write-Output "New script file created: $newFilePath (Generated: $Complexity complexity)"
                    } else {
                        Write-Output "New script file created: $newFilePath"
                    }
                }
            }
            else {
                Write-Verbose "Operation cancelled or skipped."
            }
        }
        catch {
            if ($_.Exception -and $_.Exception.Message) {
                Write-Error "An error occurred: $($_.Exception.Message)"
            } else {
                Write-Error "An error occurred, but no additional information is available."
            }
        }
    }
    end {
        if ($?) {
            Write-Debug -Message "End '$($MyInvocation.MyCommand.Name)' at '$(Get-Date)'"
        }
    }
}