src/public/System/New-AitherModule.ps1

#Requires -Version 7.0

<#
.SYNOPSIS
    Scaffolds a new AitherZero PowerShell module.

.DESCRIPTION
    Creates a standard PowerShell module structure compatible with AitherZero's build system.
    Includes source directories (public/private), manifest, and build script.

.PARAMETER Name
    The name of the module.

.PARAMETER Path
    The parent directory where the module folder will be created. Defaults to current location.

.PARAMETER Description
    Module description for the manifest.

.PARAMETER Author
    Module author. Defaults to current user or git config.

.PARAMETER Version
    Initial version. Defaults to '0.0.1'.

.PARAMETER Force
    Overwrite existing module files.

.EXAMPLE
    New-AitherModule -Name "MyFeature" -Path "./library/modules"
#>

function New-AitherModule {
    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory, Position = 0, ValueFromPipeline)]
        [string]$Name,

        [Parameter(Position = 1)]
        [string]$Path = '.',

        [string]$Description = "AitherZero module for $Name",
        [string]$Author = $env:USERNAME,
        [string]$Version = "0.0.1",
        [switch]$Force
    )

    process {
        $modulePath = Join-Path $Path $Name
        
        if (Test-Path $modulePath) {
            if (-not $Force) {
                Write-AitherLog -Level Error -Message "Module directory '$modulePath' already exists. Use -Force to overwrite." -Source 'New-AitherModule'
                throw "Module directory '$modulePath' already exists. Use -Force to overwrite."
            }
            Write-AitherLog -Level Warning -Message "Overwriting existing module at '$modulePath'" -Source 'New-AitherModule'
        }

        if ($PSCmdlet.ShouldProcess($modulePath, "Create module structure")) {
            # Create directories
            $dirs = @(
                "src/public",
                "src/private",
                "tests",
                "bin"
            )

            foreach ($dir in $dirs) {
                New-Item -Path (Join-Path $modulePath $dir) -ItemType Directory -Force | Out-Null
            }

            # Create Module Manifest (.psd1)
            $manifestPath = Join-Path $modulePath "$Name.psd1"
            $manifestContent = @{
                RootModule = "$Name.psm1"
                ModuleVersion = $Version
                GUID = [Guid]::NewGuid().ToString()
                Author = $Author
                CompanyName = "AitherZero"
                Copyright = "(c) $(Get-Date -Format 'yyyy') $Author. All rights reserved."
                Description = $Description
                PowerShellVersion = '7.0'
                FunctionsToExport = @('*')
                CmdletsToExport = @()
                VariablesToExport = @('*')
                AliasesToExport = @()
                PrivateData = @{
                    PSData = @{
                        Tags = @('AitherZero', 'Module')
                        ProjectUri = ''
                        LicenseUri = ''
                    }
                }
            }

            # Convert hashtable to string manually or use New-ModuleManifest for proper formatting
            # New-ModuleManifest is safer and cleaner
            if (Test-Path $manifestPath) {
                if ($Force) {
                    Remove-Item -Path $manifestPath -Force
                } else {
                    Write-Error "Manifest file '$manifestPath' already exists. Use -Force to overwrite."
                    return
                }
            }
            
            New-ModuleManifest -Path $manifestPath -RootModule "$Name.psm1" -ModuleVersion $Version -Author $Author -Description $Description -PowerShellVersion '7.0' -FunctionsToExport '*'

            # Create Module Script (.psm1) - Loader logic
            $psm1Path = Join-Path $modulePath "$Name.psm1"
            $psm1Content = @"
# AitherZero Module Loader
# Auto-loads functions from src/public and src/private

\$publicFunctions = Get-ChildItem -Path (Join-Path \$PSScriptRoot 'src/public') -Filter '*.ps1' -Recurse
\$privateFunctions = Get-ChildItem -Path (Join-Path \$PSScriptRoot 'src/private') -Filter '*.ps1' -Recurse

foreach (\$script in \$privateFunctions) {
    . \$script.FullName
}

foreach (\$script in \$publicFunctions) {
    . \$script.FullName
    Export-ModuleMember -Function \$script.BaseName
}
"@

            Set-Content -Path $psm1Path -Value $psm1Content

            # Create Build Script (basic)
            $buildPath = Join-Path $modulePath "build.ps1"
            $buildContent = @"
# Basic Build Script
param([string]\$OutputPath = './bin')

\$moduleName = '$Name'
Write-Host "Building \$moduleName..."

# Copy to bin (simulation of build)
Copy-Item -Path "./\$moduleName.psm1" -Destination "\$OutputPath/\$moduleName.psm1" -Force
Copy-Item -Path "./\$moduleName.psd1" -Destination "\$OutputPath/\$moduleName.psd1" -Force

Write-Host "Build complete."
"@

            Set-Content -Path $buildPath -Value $buildContent

            # Create Sample Function
            $sampleFuncPath = Join-Path $modulePath "src/public/Get-$Name.ps1"
            $sampleFuncContent = @"
function Get-$Name {
    <#
    .SYNOPSIS
        Sample function for $Name
    #>
    [CmdletBinding()]
    param()
    
    Write-Output "Hello from $Name"
}
"@

            Set-Content -Path $sampleFuncPath -Value $sampleFuncContent

            Write-AitherLog -Level Information -Message "Module '$Name' created successfully at '$modulePath'" -Source 'New-AitherModule'
            
            return Get-Item $modulePath
        }
    }
}