EnhancedLoggingAO.psm1

#Region '.\Private\AppendCSVLog.ps1' -1

#Unique Tracking ID: 737397f0-c74e-4087-9b99-279b520b7448, Timestamp: 2024-03-20 12:25:26
function AppendCSVLog {
    param (
        [string]$Message,
        [string]$CSVFilePath_1001
           
    )
    
    $csvData = [PSCustomObject]@{
        TimeStamp    = (Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
        ComputerName = $env:COMPUTERNAME
        Message      = $Message
    }
    
    $csvData | Export-Csv -Path $CSVFilePath_1001 -Append -NoTypeInformation -Force
}
#EndRegion '.\Private\AppendCSVLog.ps1' 17
#Region '.\Private\CreateEventSourceAndLog.ps1' -1

#Unique Tracking ID: 4362313d-3c19-4d0c-933d-99438a6da297, Timestamp: 2024-03-20 12:25:26

function CreateEventSourceAndLog {
    param (
        [string]$LogName,
        [string]$EventSource
    )
    
    
    # Validate parameters
    if (-not $LogName) {
        Write-Warning "LogName is required."
        return
    }
    if (-not $EventSource) {
        Write-Warning "Source is required."
        return
    }
    
    # Function to create event log and source
    function CreateEventLogSource($logName, $EventSource) {
        try {
            if ($PSVersionTable.PSVersion.Major -lt 6) {
                New-EventLog -LogName $logName -Source $EventSource
            }
            else {
                [System.Diagnostics.EventLog]::CreateEventSource($EventSource, $logName)
            }
            Write-Host "Event source '$EventSource' created in log '$logName'" -ForegroundColor Green
        }
        catch {
            Write-Warning "Error creating the event log. Make sure you run PowerShell as an Administrator."
        }
    }
    
    # Check if the event log exists
    if (-not (Get-WinEvent -ListLog $LogName -ErrorAction SilentlyContinue)) {
        # CreateEventLogSource $LogName $EventSource
    }
    # Check if the event source exists
    elseif (-not ([System.Diagnostics.EventLog]::SourceExists($EventSource))) {
        # Unregister the source if it's registered with a different log
        $existingLogName = (Get-WinEvent -ListLog * | Where-Object { $_.LogName -contains $EventSource }).LogName
        if ($existingLogName -ne $LogName) {
            Remove-EventLog -Source $EventSource -ErrorAction SilentlyContinue
        }
        # CreateEventLogSource $LogName $EventSource
    }
    else {
        Write-Host "Event source '$EventSource' already exists in log '$LogName'" -ForegroundColor Yellow
    }
}
    
# $LogName = (Get-Date -Format "HHmmss") + "_$LoggingDeploymentName"
# $EventSource = (Get-Date -Format "HHmmss") + "_$LoggingDeploymentName"
    
# Call the Create-EventSourceAndLog function
# CreateEventSourceAndLog -LogName $LogName -EventSource $EventSource
    
# Call the Write-CustomEventLog function with custom parameters and level
# Write-CustomEventLog -LogName $LogName -EventSource $EventSource -EventMessage "Outlook Signature Restore completed with warnings." -EventID 1001 -Level 'WARNING'
#EndRegion '.\Private\CreateEventSourceAndLog.ps1' 62
#Region '.\Private\Export-EventLog.ps1' -1

#Unique Tracking ID: c00ecaca-dd4b-4c7c-b80e-566b2f627e32, Timestamp: 2024-03-20 12:25:26
function Export-EventLog {
    param (
        [Parameter(Mandatory = $true)]
        [string]$LogName,
        [Parameter(Mandatory = $true)]
        [string]$ExportPath
    )
    
    try {
        wevtutil epl $LogName $ExportPath
    
        if (Test-Path $ExportPath) {
            Write-EnhancedLog -Message "Event log '$LogName' exported to '$ExportPath'" -Level "INFO" -ForegroundColor ([ConsoleColor]::Green)
        }
        else {
            Write-EnhancedLog -Message "Event log '$LogName' not exported: File does not exist at '$ExportPath'" -Level "WARNING" -ForegroundColor ([ConsoleColor]::Yellow)
        }
    }
    catch {
        Write-EnhancedLog -Message "Error exporting event log '$LogName': $($_.Exception.Message)" -Level "ERROR" -ForegroundColor ([ConsoleColor]::Red)
    }
}
    
# # Example usage
# $LogName = '$LoggingDeploymentNameLog'
# # $ExportPath = 'Path\to\your\exported\eventlog.evtx'
# $ExportPath = "C:\code\$LoggingDeploymentName\exports\Logs\$logname.evtx"
# Export-EventLog -LogName $LogName -ExportPath $ExportPath
#EndRegion '.\Private\Export-EventLog.ps1' 30
#Region '.\Private\Initialize-CSVDirectory.ps1' -1

function Initialize-CSVDirectory {
    param (
        [string]$deploymentName,
        [string]$computerName
    )

    $isWindowsOS = $false
    if ($PSVersionTable.PSVersion.Major -ge 6) {
        $isWindowsOS = $isWindowsOS -or ($PSVersionTable.Platform -eq 'Win32NT')
    } else {
        $isWindowsOS = $isWindowsOS -or ($env:OS -eq 'Windows_NT')
    }

    $baseScriptPath = if ($isWindowsOS) { "C:\code" } else { "/home/code" }
    $scriptPath_1001 = Join-Path -Path $baseScriptPath -ChildPath $deploymentName
    $CSVDir_1001 = Join-Path -Path $scriptPath_1001 -ChildPath "exports/CSV"
    $CSVFilePath_1001 = Join-Path -Path $CSVDir_1001 -ChildPath "$computerName"

    try {
        if (-not (Test-Path $CSVFilePath_1001)) {
            Write-Host "Did not find CSV directory at $CSVFilePath_1001" -ForegroundColor Yellow
            Write-Host "Creating CSV directory at $CSVFilePath_1001" -ForegroundColor Yellow
            New-Item -ItemType Directory -Path $CSVFilePath_1001 -Force -ErrorAction Stop | Out-Null
            Write-Host "Created CSV directory at $CSVFilePath_1001" -ForegroundColor Green
        }

        return @{
            CSVFilePath = $CSVFilePath_1001
        }
    } catch {
        Write-Host "An error occurred while initializing CSV directory: $_" -ForegroundColor Red
    }
}

# # Example usage of Initialize-CSVDirectory
# try {
# $csvInitResult = Initialize-CSVDirectory -deploymentName "$LoggingDeploymentName" -computerName $env:COMPUTERNAME
# Write-Host "CSV initialization successful. CSV directory path: $($csvInitResult.CSVFilePath)" -ForegroundColor Green
# } catch {
# Write-Host "CSV initialization failed: $_" -ForegroundColor Red
# }
#EndRegion '.\Private\Initialize-CSVDirectory.ps1' 42
#Region '.\Private\Write-EventLogMessage.ps1' -1

#Unique Tracking ID: 132a90f9-6ba2-49cd-878b-279deadb8e22, Timestamp: 2024-03-20 12:25:26

function Write-EventLogMessage {
    param (
        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$Message,
    
        [string]$LogName = "$LoggingDeploymentName",
        [string]$EventSource,
    
        [int]$EventID = 1000  # Default event ID
    )
    
    $ErrorActionPreference = 'SilentlyContinue'
    $hadError = $false
    
    try {
        if (-not $EventSource) {
            throw "EventSource is required."
        }
    
        if ($PSVersionTable.PSVersion.Major -lt 6) {
            # PowerShell version is less than 6, use Write-EventLog
            Write-EventLog -LogName $logName -Source $EventSource -EntryType Information -EventId $EventID -Message $Message
        }
        else {
            # PowerShell version is 6 or greater, use System.Diagnostics.EventLog
            $eventLog = New-Object System.Diagnostics.EventLog($logName)
            $eventLog.Source = $EventSource
            $eventLog.WriteEntry($Message, [System.Diagnostics.EventLogEntryType]::Information, $EventID)
        }
    
        # Write-Host "Event log entry created: $Message"
    }
    catch {
        Write-Host "Error creating event log entry: $_" 
        $hadError = $true
    }
    
    if (-not $hadError) {
        # Write-Host "Event log message writing completed successfully."
    }
}
    
#EndRegion '.\Private\Write-EventLogMessage.ps1' 46
#Region '.\Public\Export-Data.ps1' -1

function Export-Data {
    <#
.SYNOPSIS
Exports data to various formats including CSV, JSON, XML, HTML, PlainText, Excel, PDF, Markdown, and YAML.
 
.DESCRIPTION
The Export-Data function exports provided data to multiple file formats based on switches provided. It supports CSV, JSON, XML, GridView (for display only), HTML, PlainText, Excel, PDF, Markdown, and YAML formats. This function is designed to work with any PSObject.
 
.PARAMETER Data
The data to be exported. This parameter accepts input of type PSObject.
 
.PARAMETER BaseOutputPath
The base path for output files without file extension. This path is used to generate filenames for each export format.
 
.PARAMETER IncludeCSV
Switch to include CSV format in the export.
 
.PARAMETER IncludeJSON
Switch to include JSON format in the export.
 
.PARAMETER IncludeXML
Switch to include XML format in the export.
 
.PARAMETER IncludeGridView
Switch to display the data in a GridView.
 
.PARAMETER IncludeHTML
Switch to include HTML format in the export.
 
.PARAMETER IncludePlainText
Switch to include PlainText format in the export.
 
.PARAMETER IncludePDF
Switch to include PDF format in the export. Requires intermediate HTML to PDF conversion.
 
.PARAMETER IncludeExcel
Switch to include Excel format in the export.
 
.PARAMETER IncludeMarkdown
Switch to include Markdown format in the export. Custom or use a module if available.
 
.PARAMETER IncludeYAML
Switch to include YAML format in the export. Requires 'powershell-yaml' module.
 
.EXAMPLE
PS> $data = Get-Process | Select-Object -First 10
PS> Export-Data -Data $data -BaseOutputPath "C:\exports\mydata" -IncludeCSV -IncludeJSON
 
This example exports the first 10 processes to CSV and JSON formats.
#>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [psobject]$Data,

        [Parameter(Mandatory = $true)]
        [string]$BaseOutputPath,

        [switch]$IncludeCSV,
        [switch]$IncludeJSON,
        [switch]$IncludeXML,
        [switch]$IncludeGridView,
        [switch]$IncludeHTML,
        [switch]$IncludePlainText,
        [switch]$IncludePDF, # Requires intermediate HTML to PDF conversion
        [switch]$IncludeExcel,
        [switch]$IncludeMarkdown, # Custom or use a module if available
        [switch]$IncludeYAML  # Requires 'powershell-yaml' module
    )

    Begin {




        # $modules = @('ImportExcel', 'powershell-yaml' , 'PSWriteHTML')
        # Install-MissingModules -RequiredModules $modules -Verbose


        # Setup the base path without extension
        Write-Host "BaseOutputPath before change: '$BaseOutputPath'"
        $basePathWithoutExtension = [System.IO.Path]::ChangeExtension($BaseOutputPath, $null)

        # Remove extension manually if it exists
        $basePathWithoutExtension = if ($BaseOutputPath -match '\.') {
            $BaseOutputPath.Substring(0, $BaseOutputPath.LastIndexOf('.'))
        }
        else {
            $BaseOutputPath
        }

        # Ensure no trailing periods
        $basePathWithoutExtension = $basePathWithoutExtension.TrimEnd('.')
    }

    Process {
        try {
            if ($IncludeCSV) {
                $csvPath = "$basePathWithoutExtension.csv"
                $Data | Export-Csv -Path $csvPath -NoTypeInformation
            }

            if ($IncludeJSON) {
                $jsonPath = "$basePathWithoutExtension.json"
                $Data | ConvertTo-Json -Depth 10 | Set-Content -Path $jsonPath
            }

            if ($IncludeXML) {
                $xmlPath = "$basePathWithoutExtension.xml"
                $Data | Export-Clixml -Path $xmlPath
            }

            if ($IncludeGridView) {
                $Data | Out-GridView -Title "Data Preview"
            }

            if ($IncludeHTML) {
                # Assumes $Data is the dataset you want to export to HTML
                # and $basePathWithoutExtension is prepared earlier in your script
                
                $htmlPath = "$basePathWithoutExtension.html"
                
                # Convert $Data to HTML using PSWriteHTML
                New-HTML -Title "Data Export Report" -FilePath $htmlPath -ShowHTML {
                    New-HTMLSection -HeaderText "Data Export Details" -Content {
                        New-HTMLTable -DataTable $Data -ScrollX -HideFooter
                    }
                }
            
                Write-Host "HTML report generated: '$htmlPath'"
            }
            

            if ($IncludePlainText) {
                $txtPath = "$basePathWithoutExtension.txt"
                $Data | Out-String | Set-Content -Path $txtPath
            }

            if ($IncludeExcel) {
                $excelPath = "$basePathWithoutExtension.xlsx"
                $Data | Export-Excel -Path $excelPath
            }

            # Assuming $Data holds the objects you want to serialize to YAML
            if ($IncludeYAML) {
                $yamlPath = "$basePathWithoutExtension.yaml"
    
                # Check if the powershell-yaml module is loaded
                if (Get-Module -ListAvailable -Name powershell-yaml) {
                    Import-Module powershell-yaml

                    # Process $Data to handle potentially problematic properties
                    $processedData = $Data | ForEach-Object {
                        $originalObject = $_
                        $properties = $_ | Get-Member -MemberType Properties
                        $clonedObject = New-Object -TypeName PSObject

                        foreach ($prop in $properties) {
                            try {
                                $clonedObject | Add-Member -MemberType NoteProperty -Name $prop.Name -Value $originalObject.$($prop.Name) -ErrorAction Stop
                            }
                            catch {
                                # Optionally handle or log the error. Skipping problematic property.
                                $clonedObject | Add-Member -MemberType NoteProperty -Name $prop.Name -Value "Error serializing property" -ErrorAction SilentlyContinue
                            }
                        }

                        return $clonedObject
                    }

                    # Convert the processed data to YAML and save it with UTF-16 LE encoding
                    $processedData | ConvertTo-Yaml | Set-Content -Path $yamlPath -Encoding Unicode
                    Write-Host "YAML export completed successfully: $yamlPath"
                }
                else {
                    Write-Warning "The 'powershell-yaml' module is not installed. YAML export skipped."
                }
            }

            if ($IncludeMarkdown) {
                # You'll need to implement or find a ConvertTo-Markdown function or use a suitable module
                $markdownPath = "$basePathWithoutExtension.md"
                $Data | ConvertTo-Markdown | Set-Content -Path $markdownPath
            }

            if ($IncludePDF) {
                # Convert HTML to PDF using external tool
                # This is a placeholder for the process. You will need to generate HTML first and then convert it.
                $pdfPath = "$basePathWithoutExtension.pdf"
                # Assuming you have a Convert-HtmlToPdf function or a similar mechanism
                $htmlPath = "$basePathWithoutExtension.html"
                $Data | ConvertTo-Html | Convert-HtmlToPdf -OutputPath $pdfPath
            }

        }
        catch {
            Write-Error "An error occurred during export: $_"
        }
    }

    End {
        Write-Verbose "Export-Data function execution completed."
    }
}
#EndRegion '.\Public\Export-Data.ps1' 206
#Region '.\Public\Get-FunctionModule.ps1' -1

function Get-FunctionModule {
    param (
        [string]$FunctionName
    )

    # Get all imported modules
    $importedModules = Get-Module

    # Iterate through the modules to find which one exports the function
    foreach ($module in $importedModules) {
        if ($module.ExportedFunctions[$FunctionName]) {
            return $module.Name
        }
    }

    # If the function is not found in any module, return null
    return $null
}
#EndRegion '.\Public\Get-FunctionModule.ps1' 19
#Region '.\Public\Get-PSFCSVLogFilePath.ps1' -1

function Get-PSFCSVLogFilePath {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, Position = 0, HelpMessage = "Specify the base path where the logs will be stored.")]
        [string]$LogsPath,

        [Parameter(Mandatory = $true, Position = 1, HelpMessage = "Specify the job name to be used in the log file name.")]
        [string]$JobName,

        [Parameter(Mandatory = $true, Position = 2, HelpMessage = "Specify the name of the parent script.")]
        [string]$parentScriptName
    )

    Begin {
        Write-EnhancedLog -Message "Starting Get-PSFCSVLogFilePath function..." -Level "NOTICE"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters

        # Ensure the destination directory exists
        if (-not (Test-Path -Path $LogsPath)) {
            New-Item -ItemType Directory -Path $LogsPath -Force | Out-Null
            Write-EnhancedLog -Message "Created Logs directory at: $LogsPath" -Level "INFO"
        }
    }

    Process {
        try {
            # Get the current username
            $username = if ($env:USERNAME) { $env:USERNAME } else { "UnknownUser" }
            Write-EnhancedLog -Message "Current username: $username" -Level "INFO"

            # Log the parent script name
            Write-EnhancedLog -Message "Script name: $parentScriptName" -Level "INFO"

            # Check if running as SYSTEM
            $isSystem = Test-RunningAsSystem
            Write-EnhancedLog -Message "Is running as SYSTEM: $isSystem" -Level "INFO"

            # Get the current date for folder creation
            $currentDate = Get-Date -Format "yyyy-MM-dd"

            # Construct the hostname and timestamp for the log filename
            $hostname = $env:COMPUTERNAME
            $timestamp = Get-Date -Format "yyyy-MM-dd-HH-mm-ss"
            $logFolderPath = "$LogsPath\$currentDate\$parentScriptName"

            # Ensure the log directory exists
            if (-not (Test-Path -Path $logFolderPath)) {
                New-Item -Path $logFolderPath -ItemType Directory -Force | Out-Null
                Write-EnhancedLog -Message "Created directory for log file: $logFolderPath" -Level "INFO"
            }

            # Generate log file path based on context
            $logFilePath = if ($isSystem) {
                "$logFolderPath\$hostname-$JobName-SYSTEM-$parentScriptName-log-$timestamp.csv"
            }
            else {
                "$logFolderPath\$hostname-$JobName-$username-$parentScriptName-log-$timestamp.csv"
            }

            $logFilePath = Sanitize-LogFilePath -LogFilePath $logFilePath

            # Validate the log file path before using it
            Validate-LogFilePath -LogFilePath $logFilePath

            Write-EnhancedLog -Message "Generated PSFramework CSV log file path: $logFilePath" -Level "INFO"
            return $logFilePath
        }
        catch {
            Write-EnhancedLog -Message "An error occurred in Get-PSFCSVLogFilePath: $_" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_  # Re-throw the error after logging it
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Get-PSFCSVLogFilePath function" -Level "NOTICE"
    }
}
#EndRegion '.\Public\Get-PSFCSVLogFilePath.ps1' 79
#Region '.\Public\Get-TranscriptFilePath.ps1' -1

function Get-TranscriptFilePath {
    <#
    .SYNOPSIS
    Generates a file path for storing PowerShell transcripts.
 
    .DESCRIPTION
    The Get-TranscriptFilePath function constructs a unique transcript file path based on the provided transcript directory, job name, and parent script name. It ensures the transcript directory exists, handles context (e.g., SYSTEM account), and logs each step of the process.
 
    .PARAMETER TranscriptsPath
    The base directory where transcript files will be stored.
 
    .PARAMETER JobName
    The name of the job or task, used to distinguish different log files.
 
    .PARAMETER ParentScriptName
    The name of the parent script that is generating the transcript.
 
    .EXAMPLE
    $params = @{
        TranscriptsPath = 'C:\Transcripts'
        JobName = 'BackupJob'
        ParentScriptName = 'BackupScript.ps1'
    }
    Get-TranscriptFilePath @params
    Generates a transcript file path for a script called BackupScript.ps1.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, HelpMessage = "Provide the base path for transcripts.")]
        [ValidateNotNullOrEmpty()]
        [string]$TranscriptsPath,

        [Parameter(Mandatory = $true, HelpMessage = "Provide the job name.")]
        [ValidateNotNullOrEmpty()]
        [string]$JobName,

        [Parameter(Mandatory = $true, HelpMessage = "Provide the parent script name.")]
        [ValidateNotNullOrEmpty()]
        [string]$ParentScriptName
    )

    Begin {
        # Log the start of the function
        Write-EnhancedLog -Message "Starting Get-TranscriptFilePath function..." -Level "NOTICE"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters

        # Ensure the destination directory exists
        if (-not (Test-Path -Path $TranscriptsPath)) {
            New-Item -ItemType Directory -Path $TranscriptsPath -Force | Out-Null
            Write-EnhancedLog -Message "Created Transcripts directory at: $TranscriptsPath" -Level "INFO"
        }
    }

    Process {
        try {
            # Get the current username or fallback to "UnknownUser"
            $username = if ($env:USERNAME) { $env:USERNAME } else { "UnknownUser" }
            Write-EnhancedLog -Message "Current username: $username" -Level "INFO"

            # Log the provided parent script name
            Write-EnhancedLog -Message "Parent script name: $ParentScriptName" -Level "INFO"

            # Check if running as SYSTEM
            $isSystem = Test-RunningAsSystem
            Write-EnhancedLog -Message "Is running as SYSTEM: $isSystem" -Level "INFO"

            # Get the current date for folder structure
            $currentDate = Get-Date -Format "yyyy-MM-dd"
            Write-EnhancedLog -Message "Current date for transcript folder: $currentDate" -Level "INFO"

            # Construct the hostname and timestamp for the log file name
            $hostname = $env:COMPUTERNAME
            $timestamp = Get-Date -Format "yyyy-MM-dd-HH-mm-ss"
            $logFolderPath = Join-Path -Path $TranscriptsPath -ChildPath "$currentDate\$ParentScriptName"

            # Ensure the log directory exists
            if (-not (Test-Path -Path $logFolderPath)) {
                New-Item -Path $logFolderPath -ItemType Directory -Force | Out-Null
                Write-EnhancedLog -Message "Created directory for transcript logs: $logFolderPath" -Level "INFO"
            }

            # Generate log file path based on context (SYSTEM or user)
            $logFilePath = if ($isSystem) {
                "$logFolderPath\$hostname-$JobName-SYSTEM-$ParentScriptName-transcript-$timestamp.log"
            }
            else {
                "$logFolderPath\$hostname-$JobName-$username-$ParentScriptName-transcript-$timestamp.log"
            }

            Write-EnhancedLog -Message "Constructed log file path: $logFilePath" -Level "INFO"

            # Sanitize and validate the log file path
            $logFilePath = Sanitize-LogFilePath -LogFilePath $logFilePath
            Validate-LogFilePath -LogFilePath $logFilePath
            Write-EnhancedLog -Message "Log file path sanitized and validated: $logFilePath" -Level "INFO"

            # Return the constructed file path
            return $logFilePath
        }
        catch {
            Write-EnhancedLog -Message "An error occurred in Get-TranscriptFilePath: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Get-TranscriptFilePath function" -Level "NOTICE"
    }
}
#EndRegion '.\Public\Get-TranscriptFilePath.ps1' 112
#Region '.\Public\Handle-PSFLogging.ps1' -1

function Copy-PSFLogs {
    [CmdletBinding()]
    param (
        [string]$SourcePath,
        [string]$DestinationPath
    )

    Begin {
        Write-EnhancedLog -Message "Starting Copy-PSFLogs function..." -Level "NOTICE"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    Process {
        if (Test-Path -Path $SourcePath) {
            try {
                Copy-Item -Path "$SourcePath*" -Destination $DestinationPath -Recurse -Force -ErrorAction Stop
                Write-EnhancedLog -Message "Log files successfully copied from $SourcePath to $DestinationPath" -Level "INFO"
            }
            catch {
                Write-EnhancedLog -Message "Failed to copy logs from $SourcePath. Error: $_" -Level "ERROR"
            }
        }
        else {
            Write-EnhancedLog -Message "Log path not found: $SourcePath" -Level "WARNING"
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Copy-PSFLogs function" -Level "NOTICE"
    }
}
function Remove-PSFLogs {
    [CmdletBinding()]
    param (
        [string]$SourcePath
    )

    Begin {
        Write-EnhancedLog -Message "Starting Remove-PSFLogs function..." -Level "NOTICE"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    Process {
        if (Test-Path -Path $SourcePath) {
            try {
                Remove-Item -Path "$SourcePath*" -Recurse -Force -ErrorAction Stop
                Write-EnhancedLog -Message "Logs successfully removed from $SourcePath" -Level "INFO"
            }
            catch {
                Write-EnhancedLog -Message "Failed to remove logs from $SourcePath. Error: $_" -Level "ERROR"
            }
        }
        else {
            Write-EnhancedLog -Message "Log path not found: $SourcePath" -Level "WARNING"
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Remove-PSFLogs function" -Level "NOTICE"
    }
}
function Handle-PSFLogging {
    [CmdletBinding()]
    param (
        [string]$SystemSourcePathWindowsPS = "C:\Windows\System32\config\systemprofile\AppData\Roaming\WindowsPowerShell\PSFramework\Logs\",
        [string]$SystemSourcePathPS = "C:\Windows\System32\config\systemprofile\AppData\Roaming\PowerShell\PSFramework\Logs\",
        [string]$UserSourcePathWindowsPS = "$env:USERPROFILE\AppData\Roaming\WindowsPowerShell\PSFramework\Logs\",
        [string]$UserSourcePathPS = "$env:USERPROFILE\AppData\Roaming\PowerShell\PSFramework\Logs\",
        [string]$PSFPath = "C:\Logs\PSF",
        [string]$ParentScriptName,
        [string]$JobName,
        [bool]$SkipSYSTEMLogCopy = $false,
        [bool]$SkipSYSTEMLogRemoval = $false
    )

    Begin {
        Write-EnhancedLog -Message "Starting Handle-PSFLogging function..." -Level "NOTICE"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters

        # Get the current username and script name
        $username = if ($env:USERNAME) { $env:USERNAME } else { "UnknownUser" }
        $scriptName = [System.IO.Path]::GetFileNameWithoutExtension($MyInvocation.ScriptName)
        if (-not $scriptName) {
            $scriptName = "UnknownScript"
        }

        # Get the current date for folder creation
        $currentDate = Get-Date -Format "yyyy-MM-dd"
        $logFolderPath = "$PSFPath\$currentDate\$scriptName"

        # Ensure the destination directory exists
        if (-not (Test-Path -Path $logFolderPath)) {
            New-Item -ItemType Directory -Path $logFolderPath -Force
            Write-EnhancedLog -Message "Created destination directory at $logFolderPath" -Level "INFO"
        }
    }

    Process {
        # Copy logs from both SYSTEM profile paths
        
        if (-not $SkipSYSTEMLogCopy) {
            Copy-PSFLogs -SourcePath $SystemSourcePathWindowsPS -DestinationPath $logFolderPath
            Write-EnhancedLog -Message "Copied SYSTEM logs from $SystemSourcePathWindowsPS to $logFolderPath." -Level "INFO"
        
            Copy-PSFLogs -SourcePath $SystemSourcePathPS -DestinationPath $logFolderPath
            Write-EnhancedLog -Message "Copied SYSTEM logs from $SystemSourcePathPS to $logFolderPath." -Level "INFO"
        }
        else {
            Write-EnhancedLog -Message "Skipping SYSTEM log copy as per the provided parameter." -Level "INFO"
        }

        # Copy logs from the user's profile paths for both PowerShell versions
        Copy-PSFLogs -SourcePath $UserSourcePathWindowsPS -DestinationPath $logFolderPath
        Copy-PSFLogs -SourcePath $UserSourcePathPS -DestinationPath $logFolderPath

        # Verify that the files have been copied
        if (Test-Path -Path $logFolderPath) {
            Write-EnhancedLog -Message "Logs successfully processed to $logFolderPath" -Level "INFO"
        }
        else {
            Write-EnhancedLog -Message "Failed to process log files." -Level "ERROR"
        }

        # Remove logs from the SYSTEM profile paths
        if (-not $SkipSYSTEMLogRemoval) {
            # Remove logs from the SYSTEM profile paths
            Remove-PSFLogs -SourcePath $SystemSourcePathWindowsPS
            Write-EnhancedLog -Message "Removed SYSTEM logs from $SystemSourcePathWindowsPS." -Level "INFO"
            
            Remove-PSFLogs -SourcePath $SystemSourcePathPS
            Write-EnhancedLog -Message "Removed SYSTEM logs from $SystemSourcePathPS." -Level "INFO"
        }
        else {
            Write-EnhancedLog -Message "Skipping SYSTEM log removal as per the provided parameter." -Level "INFO"
        }

        # Remove logs from the User profile paths
        Remove-PSFLogs -SourcePath $UserSourcePathWindowsPS
        Remove-PSFLogs -SourcePath $UserSourcePathPS

        # Rename SYSTEM logs in PSF to append SYSTEM to easily identify these files
        $RenamePSFLogFilesParams = @{
            LogDirectoryPath = $logFolderPath 
            ParentScriptName = $ParentScriptName
            JobName          = $jobName
        }
        Rename-PSFLogFilesWithUsername @RenamePSFLogFilesParams
    }

    End {
        Write-EnhancedLog -Message "Exiting Handle-PSFLogging function" -Level "NOTICE"
    }
}
# $HandlePSFLoggingParams = @{
# SystemSourcePathWindowsPS = "C:\Windows\System32\config\systemprofile\AppData\Roaming\WindowsPowerShell\PSFramework\Logs\"
# SystemSourcePathPS = "C:\Windows\System32\config\systemprofile\AppData\Roaming\PowerShell\PSFramework\Logs\"
# UserSourcePathWindowsPS = "$env:USERPROFILE\AppData\Roaming\WindowsPowerShell\PSFramework\Logs\"
# UserSourcePathPS = "$env:USERPROFILE\AppData\Roaming\PowerShell\PSFramework\Logs\"
# PSFPath = "C:\Logs\PSF"
# }

# Handle-PSFLogging @HandlePSFLoggingParams
#EndRegion '.\Public\Handle-PSFLogging.ps1' 163
#Region '.\Public\Initialize-ScriptAndLogging.ps1' -1

$LoggingDeploymentName = $config.LoggingDeploymentName


function Initialize-ScriptAndLogging {
    $isWindowsOS = $false
    if ($PSVersionTable.PSVersion.Major -ge 6) {
        $isWindowsOS = $isWindowsOS -or ($PSVersionTable.Platform -eq 'Win32NT')
    } else {
        $isWindowsOS = $isWindowsOS -or ($env:OS -eq 'Windows_NT')
    }

    $deploymentName = "$LoggingDeploymentName" # Replace this with your actual deployment name
    $baseScriptPath = if ($isWindowsOS) { "C:\code" } else { "/home/code" }
    $scriptPath_1001 = Join-Path -Path $baseScriptPath -ChildPath $deploymentName
    $computerName = if ($isWindowsOS) { $env:COMPUTERNAME } else { (hostname) }

    try {
        if (-not (Test-Path -Path $scriptPath_1001)) {
            New-Item -ItemType Directory -Path $scriptPath_1001 -Force | Out-Null
            Write-Host "Created directory: $scriptPath_1001" -ForegroundColor Green
        }

        $Filename = "$LoggingDeploymentName"
        $logDir = Join-Path -Path $scriptPath_1001 -ChildPath "exports/Logs/$computerName"
        $logPath = Join-Path -Path $logDir -ChildPath "$(Get-Date -Format 'yyyy-MM-dd-HH-mm-ss')"

        if (-not (Test-Path $logPath)) {
            Write-Host "Did not find log directory at $logPath" -ForegroundColor Yellow
            Write-Host "Creating log directory at $logPath" -ForegroundColor Yellow
            New-Item -ItemType Directory -Path $logPath -Force -ErrorAction Stop | Out-Null
            Write-Host "Created log directory at $logPath" -ForegroundColor Green
        }

        $logFile = Join-Path -Path $logPath -ChildPath "$Filename-Transcript.log"
        Start-Transcript -Path $logFile -ErrorAction Stop | Out-Null

        return @{
            ScriptPath  = $scriptPath_1001
            Filename    = $Filename
            LogPath     = $logPath
            LogFile     = $logFile
        }
    } catch {
        Write-Host "An error occurred while initializing script and logging: $_" -ForegroundColor Red
    }
}

# Example usage of Initialize-ScriptAndLogging
# try {
# $initResult = Initialize-ScriptAndLogging
# Write-Host "Initialization successful. Log file path: $($initResult.LogFile)" -ForegroundColor Green
# } catch {
# Write-Host "Initialization failed: $_" -ForegroundColor Red
# }
#EndRegion '.\Public\Initialize-ScriptAndLogging.ps1' 55
#Region '.\Public\Log-And-Execute-Step.ps1' -1

function Log-And-Execute-Step {
    [CmdletBinding()]
    param ()

    Begin {
        Write-EnhancedLog -Message "Starting Log-And-Execute-Step function" -Level "INFO"
    }

    Process {
        try {
            $global:currentStep++
            $totalSteps = $global:steps.Count
            $step = $global:steps[$global:currentStep - 1]
            Write-EnhancedLog -Message "Step [$global:currentStep/$totalSteps]: $($step.Description)" -Level "INFO"
            
            & $step.Action
        } catch {
            Write-EnhancedLog -Message "Error in step: $($step.Description) - $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Log-And-Execute-Step function" -Level "INFO"
    }
}

# Example usage
# Log-And-Execute-Step
#EndRegion '.\Public\Log-And-Execute-Step.ps1' 30
#Region '.\Public\Remove-LogsFolder.ps1' -1

function Remove-LogsFolder {
    <#
    .SYNOPSIS
    Removes the logs folder located at C:\Logs and validates the removal.
 
    .DESCRIPTION
    The Remove-LogsFolder function removes the logs folder located at C:\Logs using the Remove-EnhancedItem function. It validates the existence of the folder before and after removal to ensure successful deletion.
 
    .PARAMETER LogFolderPath
    The path of the logs folder to be removed. Default is C:\Logs.
 
    .PARAMETER MaxRetries
    The maximum number of retries to attempt for removal. Default is 5.
 
    .PARAMETER RetryInterval
    The interval in seconds between retries. Default is 10 seconds.
 
    .EXAMPLE
    Remove-LogsFolder
    Removes the logs folder at C:\Logs.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false)]
        [string]$LogFolderPath = "C:\Logs",

        [Parameter(Mandatory = $false)]
        [int]$MaxRetries = 5,

        [Parameter(Mandatory = $false)]
        [int]$RetryInterval = 10
    )

    Begin {
        Write-EnhancedLog -Message "Starting Remove-LogsFolder function" -Level "Notice"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    Process {
        try {
            # Validate before removal
            $validationResultsBefore = Validate-PathExistsWithLogging -Paths $LogFolderPath

            if ($validationResultsBefore.TotalValidatedFiles -gt 0) {
                Write-EnhancedLog -Message "Attempting to remove logs folder: $LogFolderPath" -Level "INFO"
                
                $removeParams = @{
                    Path               = $LogFolderPath
                    ForceKillProcesses = $true
                    MaxRetries         = $MaxRetries
                    RetryInterval      = $RetryInterval
                }
                Remove-EnhancedItem @removeParams

                # Validate after removal
                $validationResultsAfter = Validate-PathExistsWithLogging -Paths $LogFolderPath

                if ($validationResultsAfter.TotalValidatedFiles -gt 0) {
                    Write-EnhancedLog -Message "Logs folder $LogFolderPath still exists after attempting to remove. Manual intervention may be required." -Level "ERROR"
                }
                else {
                    Write-EnhancedLog -Message "Logs folder $LogFolderPath successfully removed." -Level "CRITICAL"
                }
            }
            else {
                Write-EnhancedLog -Message "Logs folder $LogFolderPath does not exist. No action taken." -Level "WARNING"
            }
        }
        catch {
            Write-EnhancedLog -Message "Error during removal of logs folder at path: $LogFolderPath. Error: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Remove-LogsFolder function" -Level "Notice"
    }
}

# Example usage
# Remove-LogsFolder
#EndRegion '.\Public\Remove-LogsFolder.ps1' 83
#Region '.\Public\Rename-PSFLogFilesWithUsername.ps1' -1

function Rename-PSFLogFilesWithUsername {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$LogDirectoryPath,

        [Parameter(Mandatory = $true, Position = 1)]
        [string]$ParentScriptName,

        [Parameter(Mandatory = $true, Position = 2)]
        [string]$JobName
    )

    Begin {
        Write-EnhancedLog -Message "Starting Rename-PSFLogFilesWithUsername function..." -Level "NOTICE"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    Process {
        Write-EnhancedLog -Message "Starting the renaming process for log files in directory: $LogDirectoryPath" -Level "INFO"

        # Get all log files in the specified directory
        $logFiles = Get-ChildItem -Path $LogDirectoryPath -Filter "*.log"

        if ($logFiles.Count -eq 0) {
            Write-EnhancedLog -Message "No log files found in the directory." -Level "WARNING"
            return
        }

        Write-EnhancedLog -Message "Found $($logFiles.Count) log files to process." -Level "INFO"

        foreach ($logFile in $logFiles) {
            try {
                Write-EnhancedLog -Message "Processing file: $($logFile.FullName)" -Level "INFO"

                # Import the log file as CSV
                $logEntries = Import-Csv -Path $logFile.FullName

                # Extract the username, timestamp, and computer name from the first entry in the CSV
                $firstEntry = $logEntries | Select-Object -First 1
                $username = $firstEntry.Username
                $timestamp = $firstEntry.Timestamp
                $computerName = $firstEntry.ComputerName

                if (-not $username) {
                    Write-EnhancedLog -Message "No username found in $($logFile.Name). Skipping file." -Level "WARNING"
                    continue
                }

                if (-not $timestamp) {
                    $timestamp = "NoTimestamp"
                    Write-EnhancedLog -Message "No timestamp found in $($logFile.Name). Defaulting to 'NoTimestamp'." -Level "WARNING"
                }

                if (-not $computerName) {
                    $computerName = "UnknownComputer"
                    Write-EnhancedLog -Message "No computer name found in $($logFile.Name). Defaulting to 'UnknownComputer'." -Level "WARNING"
                }

                Write-EnhancedLog -Message "Username found in file: $username" -Level "INFO"
                Write-EnhancedLog -Message "Timestamp found in file: $timestamp" -Level "INFO"
                Write-EnhancedLog -Message "Computer name found in file: $computerName" -Level "INFO"

                # Remove the domain part if present in the username
                if ($username -match '^[^\\]+\\(.+)$') {
                    $username = $matches[1]
                }

                Write-EnhancedLog -Message "Processed username: $username" -Level "INFO"

                # Sanitize the username, timestamp, and computer name
                $safeUsername = $username -replace '[\\/:*?"<>|]', '_'
                $safeTimestamp = $timestamp -replace '[\\/:*?"<>|]', '_'
                $safeComputerName = $computerName -replace '[\\/:*?"<>|]', '_'

                Write-EnhancedLog -Message "Sanitized username: $safeUsername" -Level "INFO"
                Write-EnhancedLog -Message "Sanitized timestamp: $safeTimestamp" -Level "INFO"
                Write-EnhancedLog -Message "Sanitized computer name: $safeComputerName" -Level "INFO"

                # Generate a unique identifier
                $uniqueId = [guid]::NewGuid().ToString()

                # Construct the new file name with the GUID
                $fileExtension = [System.IO.Path]::GetExtension($logFile.FullName)
                $newFileName = "$JobName-$safeUsername-$safeComputerName-$ParentScriptName-$safeTimestamp-$uniqueId$fileExtension"
                $newFilePath = [System.IO.Path]::Combine($logFile.DirectoryName, $newFileName)
                Write-EnhancedLog -Message "Attempting to rename to: $newFilePath" -Level "INFO"

                # Rename the file
                Rename-Item -Path $logFile.FullName -NewName $newFileName -Force
                Write-EnhancedLog -Message "Successfully renamed $($logFile.FullName) to $newFileName" -Level "INFO"
            }
            catch {
                Write-EnhancedLog -Message "Failed to process $($logFile.FullName): $_" -Level "ERROR"
                Write-EnhancedLog -Message "Possible cause: The file name or path may contain invalid characters or the file might be in use." -Level "ERROR"
            }
        }

        Write-EnhancedLog -Message "Finished processing all log files." -Level "INFO"
    }

    End {
        Write-EnhancedLog -Message "Exiting Rename-PSFLogFilesWithUsername function" -Level "NOTICE"
    }
}
#EndRegion '.\Public\Rename-PSFLogFilesWithUsername.ps1' 106
#Region '.\Public\Sanitize-LogFilePath.ps1' -1

function Sanitize-LogFilePath {
    [CmdletBinding()]
    param (
        [string]$LogFilePath
    )

    try {
        Write-EnhancedLog -Message "Starting Sanitize-LogFilePath function..." -Level "NOTICE"
        Write-EnhancedLog -Message "Original LogFilePath: $LogFilePath" -Level "INFO"

        # Trim leading and trailing whitespace
        $LogFilePath = $LogFilePath.Trim()
        Write-EnhancedLog -Message "LogFilePath after trim: $LogFilePath" -Level "INFO"

        # Replace multiple spaces with a single space
        $LogFilePath = $LogFilePath -replace '\s+', ' '
        Write-EnhancedLog -Message "LogFilePath after removing multiple spaces: $LogFilePath" -Level "INFO"

        # Replace illegal characters (preserve drive letter and colon)
        if ($LogFilePath -match '^([a-zA-Z]):\\') {
            $drive = $matches[1]
            $LogFilePath = $LogFilePath -replace '[<>:"|?*]', '_'
            $LogFilePath = "$drive`:$($LogFilePath.Substring(2))"
        }
        else {
            # Handle cases where the path doesn't start with a drive letter
            $LogFilePath = $LogFilePath -replace '[<>:"|?*]', '_'
        }
        Write-EnhancedLog -Message "LogFilePath after replacing invalid characters: $LogFilePath" -Level "INFO"

        # Replace multiple backslashes with a single backslash
        $LogFilePath = [System.Text.RegularExpressions.Regex]::Replace($LogFilePath, '\\+', '\')
        Write-EnhancedLog -Message "LogFilePath after replacing multiple slashes: $LogFilePath" -Level "INFO"

        # Ensure the path is still rooted
        if (-not [System.IO.Path]::IsPathRooted($LogFilePath)) {
            throw "The LogFilePath is not rooted: $LogFilePath"
        }

        Write-EnhancedLog -Message "Sanitized LogFilePath: $LogFilePath" -Level "INFO"
        Write-EnhancedLog -Message "Exiting Sanitize-LogFilePath function" -Level "NOTICE"
        return $LogFilePath
    }
    catch {
        Write-EnhancedLog -Message "An error occurred in Sanitize-LogFilePath: $_" -Level "ERROR"
        Handle-Error -ErrorRecord $_
        throw $_  # Re-throw the error after logging it
    }
}
#EndRegion '.\Public\Sanitize-LogFilePath.ps1' 50
#Region '.\Public\Validate-LogFilePath.ps1' -1

function Validate-LogFilePath {
    [CmdletBinding()]
    param (
        [string]$LogFilePath
    )

    try {
        Write-EnhancedLog -Message "Starting Validate-LogFilePath function..." -Level "NOTICE"
        Write-EnhancedLog -Message "Validating LogFilePath: $LogFilePath" -Level "INFO"

        # Check for invalid characters in the file path
        if ($LogFilePath -match "[<>""|?*]") {
            Write-EnhancedLog -Message "Warning: The LogFilePath contains invalid characters." -Level "WARNING"
        }

        # Check for double backslashes which may indicate an error in path generation
        if ($LogFilePath -match "\\\\") {
            Write-EnhancedLog -Message "Warning: The LogFilePath contains double backslashes." -Level "WARNING"
        }

        Write-EnhancedLog -Message "Validation complete for LogFilePath: $LogFilePath" -Level "INFO"
        Write-EnhancedLog -Message "Exiting Validate-LogFilePath function" -Level "NOTICE"
    }
    catch {
        Write-EnhancedLog -Message "An error occurred in Validate-LogFilePath: $_" -Level "ERROR"
        Handle-Error -ErrorRecord $_
        throw $_  # Re-throw the error after logging it
    }
}
#EndRegion '.\Public\Validate-LogFilePath.ps1' 30
#Region '.\Public\Write-LogMessage.ps1' -1

function Generate-UniqueBase {
    <#
    .SYNOPSIS
    Generates a unique base identifier using the current timestamp, process ID, and a random number.
 
    .DESCRIPTION
    The Generate-UniqueBase function creates a unique identifier composed of parts of the current timestamp, the process ID, and a random number. This ensures uniqueness for various applications that require a simple, unique identifier.
 
    .PARAMETER TimestampFormat
    Specifies the format of the timestamp to use in the identifier.
 
    .PARAMETER ProcessIdLength
    Specifies the number of digits to use from the process ID.
 
    .PARAMETER RandomPartMin
    Specifies the minimum value for the random number part.
 
    .PARAMETER RandomPartMax
    Specifies the maximum value for the random number part.
 
    .EXAMPLE
    Generate-UniqueBase -TimestampFormat "yyMMddHHmm" -ProcessIdLength 4 -RandomPartMin 10 -RandomPartMax 99
    Generates a unique identifier using the specified timestamp format, process ID length, and random number range.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $false)]
        [string]$TimestampFormat = "yyMMddHHmm",

        [Parameter(Mandatory = $false)]
        [int]$ProcessIdLength = 4,

        [Parameter(Mandatory = $false)]
        [int]$RandomPartMin = 10,

        [Parameter(Mandatory = $false)]
        [int]$RandomPartMax = 99
    )

    Begin {
        Write-EnhancedLog -Message "Starting Generate-UniqueBase function" -Level "NOTICE"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    Process {
        try {
            # Generate the components
            $timestamp = (Get-Date).ToString($TimestampFormat)
            $processid = $PID.ToString("D$ProcessIdLength")
            $randomPart = (Get-Random -Minimum $RandomPartMin -Maximum $RandomPartMax).ToString("D2")

            Write-EnhancedLog -Message "Generated timestamp: '$timestamp', Process ID: '$processid', Random Part: '$randomPart'" -Level "INFO"

            # Adjust the components to ensure the length is 8 characters
            Write-EnhancedLog -Message "Original lengths -> Timestamp: $($timestamp.Length), Process ID: $($processid.Length), Random Part: $($randomPart.Length)" -Level "INFO"

            $uniqueBase = $timestamp.Substring($timestamp.Length - 4, 4) + $processid.Substring(0, 2) + $randomPart

            Write-EnhancedLog -Message "Generated Unique Base (before validation): '$uniqueBase', Length: $($uniqueBase.Length)" -Level "INFO"

            # Validate that the unique base is exactly 8 characters long
            if ($uniqueBase.Length -ne 8) {
                $errorMessage = "The generated unique base '$uniqueBase' is not 8 characters long. It is $($uniqueBase.Length) characters. Halting script execution."
                Write-EnhancedLog -Message $errorMessage -Level "CRITICAL" -ForegroundColor ([ConsoleColor]::Red)
                throw $errorMessage
            }

            Write-EnhancedLog -Message "Unique base successfully generated: $uniqueBase" -Level "INFO"
            return $uniqueBase
        }
        catch {
            Write-EnhancedLog -Message "An error occurred in Generate-UniqueBase function: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Generate-UniqueBase function" -Level "NOTICE"
    }
}

function Validate-EventLog {
    <#
    .SYNOPSIS
    Validates whether an event log and its associated source exist and are correctly configured.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$LogName,

        [Parameter(Mandatory = $true)]
        [string]$SourceName,

        [Parameter(Mandatory = $false)]
        [switch]$PostValidation
    )

    Begin {
        Write-EnhancedLog -Message "Starting Validate-EventLog function" -Level "NOTICE"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    Process {
        try {
            # Validate if the log exists
            Write-EnhancedLog -Message "Validating if event log '$LogName' exists." -Level "INFO"
            $logExists = @(Get-WinEvent -ListLog * | Where-Object { $_.LogName -eq $LogName }).Count -gt 0
            Write-EnhancedLog -Message "Event log '$LogName' existence: $logExists" -Level "INFO"

            # Validate if the source exists
            Write-EnhancedLog -Message "Validating if event source '$SourceName' exists." -Level "INFO"
            $sourceExists = [System.Diagnostics.EventLog]::SourceExists($SourceName)
            Write-EnhancedLog -Message "Event source '$SourceName' existence: $sourceExists" -Level "INFO"

            $sourceLogName = if ($sourceExists) { 
                [System.Diagnostics.EventLog]::LogNameFromSourceName($SourceName, ".") 
            }
            else { 
                Write-EnhancedLog -Message "Event source '$SourceName' is not associated with any log." -Level "WARNING"
                $null 
            }

            Write-EnhancedLog -Message "Event source '$SourceName' is associated with log: $sourceLogName" -Level "INFO"

            # Return the validation results as a hashtable
            $result = @{
                LogExists     = $logExists
                SourceExists  = $sourceExists
                SourceLogName = $sourceLogName
            }

            # Ensure the result is correctly returned as a hashtable
            if ($result -is [System.Collections.Hashtable]) {
                Write-EnhancedLog -Message "Returning validation result as a hashtable: LogExists = $($result['LogExists']), SourceExists = $($result['SourceExists']), SourceLogName = $($result['SourceLogName'])" -Level "INFO"
            }
            else {
                Write-EnhancedLog -Message "Unexpected data type for validation result. Expected a hashtable." -Level "ERROR"
                throw "Unexpected data type for validation result."
            }

            return $result
        }
        catch {
            Write-EnhancedLog -Message "An error occurred in Validate-EventLog function: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Validate-EventLog function" -Level "NOTICE"
    }
}

function Manage-EventLogSource {
    <#
    .SYNOPSIS
    Manages the event log source, ensuring it is correctly associated with the specified event log.
 
    .DESCRIPTION
    The Manage-EventLogSource function checks the current state of the event log and source. It handles scenarios where the log or source might not exist, or where the source is associated with a different log, and ensures that the event log and source are properly created or reassigned.
 
    .PARAMETER LogName
    The name of the event log.
 
    .PARAMETER SourceName
    The name of the event source.
 
    .PARAMETER ValidationResult
    A hashtable containing the results of the pre-validation process, including whether the log and source exist and their associations.
 
    .EXAMPLE
    Manage-EventLogSource -LogName "MyLog" -SourceName "MySource" -ValidationResult $validationResult
    Ensures that the event log "MyLog" is correctly associated with the source "MySource."
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$LogName,

        [Parameter(Mandatory = $true)]
        [string]$SourceName,

        [Parameter(Mandatory = $true)]
        [hashtable]$ValidationResult
    )

    Begin {
        Write-EnhancedLog -Message "Starting Manage-EventLogSource function" -Level "NOTICE"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    Process {
        try {
            if (-not $ValidationResult.LogExists -and -not $ValidationResult.SourceExists) {
                # Neither the log nor the source exist, create both
                Write-EnhancedLog -Message "Neither log nor source exists. Creating both." -Level "INFO"
                New-EventLog -LogName $LogName -Source $SourceName
                Write-EnhancedLog -Message "Created event log '$LogName' and source '$SourceName'." -Level "INFO"
            }
            elseif ($ValidationResult.LogExists -and $ValidationResult.SourceExists -and $ValidationResult.SourceLogName -ne $LogName) {
                # Both log and source exist but the source is associated with a different log
                Write-EnhancedLog -Message "Source exists but is associated with a different log. Recreating source." -Level "WARNING"
                Remove-EventLog -Source $SourceName
                New-EventLog -LogName $LogName -Source $SourceName
                Write-EnhancedLog -Message "Source '$SourceName' was associated with a different log ('$ValidationResult.SourceLogName'). Recreated event log '$LogName' with source '$SourceName'." -Level "WARNING"
            }
            elseif (-not $ValidationResult.LogExists -and $ValidationResult.SourceExists) {
                # Source exists but is associated with a different log, so remove the source and create the correct log and source
                Write-EnhancedLog -Message "Log does not exist, but source exists. Removing source and creating log." -Level "WARNING"
                Remove-EventLog -Source $SourceName
                New-EventLog -LogName $LogName -Source $SourceName
                Write-EnhancedLog -Message "Event source '$SourceName' was associated with a different log. Recreated event log '$LogName' with source '$SourceName'." -Level "WARNING"
            }
            elseif ($ValidationResult.LogExists -and -not $ValidationResult.SourceExists) {
                # Log exists but the source does not, so create the source
                Write-EnhancedLog -Message "Log exists, but source does not. Creating source." -Level "INFO"
                New-EventLog -LogName $LogName -Source $SourceName
                Write-EnhancedLog -Message "Added source '$SourceName' to existing event log '$LogName'." -Level "INFO"
            }
            else {
                # Both log and source exist and are correctly associated
                Write-EnhancedLog -Message "Event log '$LogName' and source '$SourceName' already exist and are correctly associated." -Level "INFO"
            }

            $DBG
        }
        catch {
            Write-EnhancedLog -Message "An error occurred in Manage-EventLogSource function: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Manage-EventLogSource function" -Level "NOTICE"
    }
}

function Sanitize-ParentScriptName {
    <#
    .SYNOPSIS
    Sanitizes the parent script name by removing spaces and any special characters.
 
    .DESCRIPTION
    The Sanitize-ParentScriptName function ensures that the parent script name is sanitized by removing spaces, special characters, and ensuring it conforms to naming conventions suitable for log names.
 
    .PARAMETER ParentScriptName
    The parent script name to sanitize.
 
    .EXAMPLE
    $sanitizedParentScriptName = Sanitize-ParentScriptName -ParentScriptName "My Script Name 2024"
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$ParentScriptName
    )

    Begin {
        Write-EnhancedLog -Message "Starting Sanitize-ParentScriptName function" -Level "NOTICE"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    Process {
        try {
            # Remove any spaces and special characters
            Write-EnhancedLog -Message "Sanitizing the parent script name: '$ParentScriptName'." -Level "INFO"
            $sanitizedParentScriptName = $ParentScriptName -replace '\s+', '' -replace '[^a-zA-Z0-9]', ''
            Write-EnhancedLog -Message "Sanitized parent script name: '$sanitizedParentScriptName'." -Level "INFO"

            return $sanitizedParentScriptName
        }
        catch {
            Write-EnhancedLog -Message "An error occurred in Sanitize-ParentScriptName function: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Sanitize-ParentScriptName function" -Level "NOTICE"
    }
}

function Sanitize-LogName {
    <#
    .SYNOPSIS
    Sanitizes the log name to ensure it is a valid string.
 
    .DESCRIPTION
    The Sanitize-LogName function checks if the log name is a valid string. If the log name is not a string, the function attempts to convert it. If it contains invalid characters or if the conversion is not possible, an error is thrown.
 
    .PARAMETER LogName
    The log name to sanitize.
 
    .EXAMPLE
    $sanitizedLogName = Sanitize-LogName -LogName $logName
    Sanitizes the provided log name and returns a clean string.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [AllowNull()]
        [AllowEmptyString()]
        [System.Object]$LogName
    )

    Begin {
        Write-EnhancedLog -Message "Starting Sanitize-LogName function" -Level "NOTICE"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    Process {
        try {
            # Ensure the LogName is a single string, not an array or hashtable
            if ($LogName -is [System.Collections.IEnumerable] -and $LogName -notlike [string]) {
                Write-EnhancedLog -Message "Log name is an array or collection. Attempting to extract the first valid string." -Level "WARNING"
                $LogName = $LogName | Where-Object { $_ -is [string] } | Select-Object -First 1
            }

            # If LogName is still not a string, throw an error
            if ($LogName -isnot [string]) {
                Write-EnhancedLog -Message "Log name is not a valid string. Actual type: $($LogName.GetType().Name)" -Level "ERROR"
                throw "Log name must be a string. Received type: $($LogName.GetType().Name)"
            }

            # Sanitize the log name by trimming and removing any unnecessary characters
            $sanitizedLogName = $LogName.Trim() -replace '[^\w-]', ''
            Write-EnhancedLog -Message "Sanitized log name: '$sanitizedLogName'" -Level "INFO"

            return $sanitizedLogName
        }
        catch {
            Write-EnhancedLog -Message "An error occurred in Sanitize-LogName function: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Sanitize-LogName function" -Level "NOTICE"
    }
}

function Sanitize-SourceName {
    <#
    .SYNOPSIS
    Sanitizes the source name by removing spaces and special characters.
 
    .DESCRIPTION
    The Sanitize-SourceName function ensures that the source name is sanitized by removing spaces, special characters, and ensuring it conforms to naming conventions suitable for log sources.
 
    .PARAMETER SourceName
    The source name to sanitize.
 
    .EXAMPLE
    $sanitizedSourceName = Sanitize-SourceName -SourceName "My Source Name 2024"
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$SourceName
    )

    Begin {
        Write-EnhancedLog -Message "Starting Sanitize-SourceName function" -Level "NOTICE"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    Process {
        try {
            # Remove any spaces and special characters
            Write-EnhancedLog -Message "Sanitizing the source name: '$SourceName'." -Level "INFO"
            $sanitizedSourceName = $SourceName -replace '\s+', '' -replace '[^a-zA-Z0-9]', ''
            Write-EnhancedLog -Message "Sanitized source name: '$sanitizedSourceName'." -Level "INFO"

            return $sanitizedSourceName
        }
        catch {
            Write-EnhancedLog -Message "An error occurred in Sanitize-SourceName function: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Sanitize-SourceName function" -Level "NOTICE"
    }
}

function Manage-EventLogs {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$ParentScriptName
    )

    Begin {
        Write-EnhancedLog -Message "Starting Manage-EventLogs function" -Level "NOTICE"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    Process {
        try {
            # Step 1: Sanitize the parent script name
            Write-EnhancedLog -Message "Sanitizing the parent script name." -Level "INFO"
            $sanitizedParentScriptName = Sanitize-ParentScriptName -ParentScriptName $ParentScriptName
            Write-EnhancedLog -Message "Sanitized parent script name: '$sanitizedParentScriptName'." -Level "INFO"

            # Step 2: Generate the unique base for the log name
            Write-EnhancedLog -Message "Generating unique base for log name." -Level "INFO"
            $uniqueBase = Generate-UniqueBase
            Write-EnhancedLog -Message "Unique base generated: $uniqueBase" -Level "INFO"

            # Step 3: Combine the unique base with the sanitized parent script name
            $logName = "$uniqueBase-$sanitizedParentScriptName"
            Write-EnhancedLog -Message "Constructed log name: $logName" -Level "INFO"

            # Step 4: Sanitize the log name
            Write-EnhancedLog -Message "Sanitizing the log name." -Level "INFO"
            $global:sanitizedlogName = Sanitize-LogName -LogName $logName
            Write-EnhancedLog -Message "Sanitized log name: '$global:sanitizedlogName'." -Level "INFO"

            # Step 5: Retrieve existing logs matching the sanitized parent script name
            Write-EnhancedLog -Message "Retrieving existing logs that match the sanitized parent script name: '$sanitizedParentScriptName'." -Level "INFO"
            $logs = @()
            try {
                $logs = @(Get-WinEvent -ListLog * | Where-Object { $_.LogName -like "*$sanitizedParentScriptName*" })
                Write-EnhancedLog -Message "Retrieved $($logs.Count) logs that match the sanitized parent script name." -Level "INFO"
            }
            catch {
                Write-EnhancedLog -Message "Failed to retrieve logs due to an error: $($_.Exception.Message)" -Level "ERROR"
                throw $_
            }

            # Step 6: Check if an existing log should be used
            if ($logs.Count -gt 0) {
                $existingLog = $logs | Select-Object -First 1
                if ($existingLog) {
                    $logName = $existingLog.LogName
                    Write-EnhancedLog -Message "Existing log found and will be used: '$logName'." -Level "INFO"
                }
            }
            else {
                Write-EnhancedLog -Message "No existing log found for sanitized parent script name: '$sanitizedParentScriptName'. Creating a new log: '$logName'." -Level "INFO"
            }

            # Return the sanitized and validated log name
            return $logName
        }
        catch {
            Write-EnhancedLog -Message "An error occurred in Manage-EventLogs function: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Manage-EventLogs function" -Level "NOTICE"
    }
}

function Construct-SourceName {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$LogName,

        [Parameter(Mandatory = $true)]
        [string]$CallerFunction
    )

    Begin {
        Write-EnhancedLog -Message "Starting Construct-SourceName function" -Level "NOTICE"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    Process {
        try {
            # Step 1: Construct the initial source name
            Write-EnhancedLog -Message "Constructing source name using LogName '$LogName' and CallerFunction '$CallerFunction'." -Level "INFO"
            $sourceName = "$LogName-$CallerFunction"
            Write-EnhancedLog -Message "Constructed source name: '$sourceName'" -Level "INFO"

            # Step 2: Sanitize the source name
            Write-EnhancedLog -Message "Sanitizing the constructed source name." -Level "INFO"
            $sanitizedSourceName = Sanitize-SourceName -SourceName $sourceName
            Write-EnhancedLog -Message "Sanitized source name: '$sanitizedSourceName'." -Level "INFO"

            return $sanitizedSourceName
        }
        catch {
            Write-EnhancedLog -Message "An error occurred in Construct-SourceName function: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Construct-SourceName function" -Level "NOTICE"
    }
}
function Initialize-EventLog {
    <#
    .SYNOPSIS
    Initializes the event log by managing logs, validating before and after operations, and managing sources.
 
    .DESCRIPTION
    The Initialize-EventLog function handles the entire process of setting up an event log. It manages the creation or retrieval of logs, validates them before and after operations, and ensures the correct association of event sources.
 
    .PARAMETER SourceName
    The name of the event source to be used.
 
    .PARAMETER ParentScriptName
    The name of the parent script to be used as part of the event log name.
 
    .EXAMPLE
    Initialize-EventLog -SourceName "MySource" -ParentScriptName "MyScript"
    Initializes an event log with the specified source and parent script name.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$SourceName,

        [Parameter(Mandatory = $true)]
        [string]$ParentScriptName
    )

    Begin {
        Write-EnhancedLog -Message "Starting Initialize-EventLog function" -Level "WARNING"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    Process {
        try {
            # Step 1: Manage Logs
            Write-EnhancedLog -Message "Managing event logs." -Level "INFO"
            try {
                Write-EnhancedLog -Message "Calling Manage-EventLogs function with ParentScriptName: '$ParentScriptName'." -Level "DEBUG"
                $global:sanitizedlogName = Manage-EventLogs -ParentScriptName $ParentScriptName
                Write-EnhancedLog -Message "Manage-EventLogs function returned log name: '$global:sanitizedlogName'." -Level "INFO"
            }
            catch {
                Write-EnhancedLog -Message "An error occurred while managing event logs: $($_.Exception.Message)" -Level "ERROR"
                throw $_
            }

            $DBG

            # Step 2: Sanitize the Log Name
            try {
                Write-EnhancedLog -Message "Sanitizing the log name returned by Manage-EventLogs." -Level "INFO"
                $global:sanitizedlogName = Sanitize-LogName -LogName $global:sanitizedlogName
                Write-EnhancedLog -Message "Sanitized log name: '$global:sanitizedlogName'." -Level "INFO"
            }
            catch {
                Write-EnhancedLog -Message "An error occurred while sanitizing the log name: $($_.Exception.Message)" -Level "ERROR"
                throw $_
            }

            # Step 3: Construct the source name using the sanitized log name and the caller function
            try {
                Write-EnhancedLog -Message "Constructing the source name using the sanitized log name and caller function." -Level "INFO"
                $global:sanitizedsourceName = Construct-SourceName -LogName $global:sanitizedlogName -CallerFunction $SourceName
                Write-EnhancedLog -Message "Constructed source name: '$global:sanitizedsourceName'." -Level "INFO"
            }
            catch {
                Write-EnhancedLog -Message "An error occurred while constructing the source name: $($_.Exception.Message)" -Level "ERROR"
                throw $_
            }

            $DBG




            # Step 4: Pre-Validation
            Write-EnhancedLog -Message "Performing pre-validation for log '$global:sanitizedlogName' and source '$global:sanitizedsourceName'." -Level "INFO"
            try {
                $validationResult = Validate-EventLog -LogName $global:sanitizedlogName -SourceName $global:sanitizedsourceName
                Write-EnhancedLog -Message "Pre-validation completed: Log exists = $($validationResult.LogExists), Source exists = $($validationResult.SourceExists)." -Level "INFO"
            }
            catch {
                Write-EnhancedLog -Message "An error occurred during pre-validation: $($_.Exception.Message)" -Level "ERROR"
                throw $_
            }

            $DBG

            # Step 5: Manage Sources
            Write-EnhancedLog -Message "Managing event log sources for log '$global:sanitizedlogName' and source '$global:sanitizedsourceName'." -Level "INFO"
            try {
                Manage-EventLogSource -LogName $global:sanitizedlogName -SourceName $global:sanitizedsourceName -ValidationResult $validationResult
                Write-EnhancedLog -Message "Event log sources managed successfully." -Level "INFO"
            }
            catch {
                Write-EnhancedLog -Message "An error occurred while managing event log sources: $($_.Exception.Message)" -Level "ERROR"
                throw $_
            }

            $DBG

            # Step 6: Post-Validation (Optional)
            Write-EnhancedLog -Message "Performing post-validation for log '$global:sanitizedlogName' and source '$global:sanitizedsourceName'." -Level "INFO"
            try {
                Validate-EventLog -LogName $global:sanitizedlogName -SourceName $global:sanitizedsourceName -PostValidation
                Write-EnhancedLog -Message "Post-validation completed successfully." -Level "INFO"
            }
            catch {
                Write-EnhancedLog -Message "An error occurred during post-validation: $($_.Exception.Message)" -Level "ERROR"
                throw $_
            }
        }
        catch {
            Write-EnhancedLog -Message "An error occurred in Initialize-EventLog function: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_
        }

        $DBG
    }

    End {
        Write-EnhancedLog -Message "Preparing to exit Initialize-EventLog function. Returning log name: '$global:sanitizedlogName'." -Level "INFO"

        # Ensure that only the log name string is returned
        try {
            if (-not $global:sanitizedlogName) {
                throw "Log name is null or empty. Cannot return a valid log name."
            }

            # Log the type of logName to ensure it's a string
            if ($global:sanitizedlogName -isnot [string]) {
                Write-EnhancedLog -Message "Log name is not a string. Actual type: $($global:sanitizedlogName.GetType().Name)" -Level "ERROR"
                throw "Unexpected type for log name. Expected string."
            }

            Write-EnhancedLog -Message "Log name '$global:sanitizedlogName' is valid and will be returned." -Level "INFO"
        }
        catch {
            Write-EnhancedLog -Message "An error occurred while finalizing the log name: $($_.Exception.Message)" -Level "ERROR"
            throw $_
        }

        $DBG

        Write-EnhancedLog -Message "Exiting Initialize-EventLog function" -Level "WARNING"
        return $global:sanitizedlogName
    }
}
function Write-LogMessage {
    <#
    .SYNOPSIS
    Writes a log message to the event log with a specified level and event ID.
 
    .DESCRIPTION
    The Write-LogMessage function writes a message to the event log. It maps custom levels to event log entry types and event IDs, determines the calling function, and ensures the event log and source are properly initialized.
 
    .PARAMETER Message
    The message to write to the event log.
 
    .PARAMETER Level
    The level of the message, which determines the event log entry type. Defaults to 'INFO'.
 
    .PARAMETER EventID
    The event ID for the log entry. Defaults to 1000.
 
    .EXAMPLE
    Write-LogMessage -Message "This is a test log message" -Level "ERROR" -EventID 3001
    Writes an error message to the event log with event ID 3001.
    #>


    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Message,

        [Parameter(Mandatory = $false)]
        [string]$Level = 'INFO',

        [Parameter(Mandatory = $false)]
        [int]$EventID = 1000
    )

    Begin {
        Write-EnhancedLog -Message "Starting Write-LogMessage function" -Level "NOTICE"
        Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters
    }

    Process {
        try {
            # Get the PowerShell call stack to determine the actual calling function
            Write-EnhancedLog -Message "Retrieving the PowerShell call stack to determine the caller function." -Level "DEBUG"
            $callStack = Get-PSCallStack
            $callerFunction = if ($callStack.Count -ge 2) { $callStack[1].Command } else { '<Unknown>' }
            Write-EnhancedLog -Message "Caller function identified as '$callerFunction'." -Level "INFO"

            # Map custom levels to event log entry types and event IDs
            Write-EnhancedLog -Message "Mapping log level '$Level' to entry type and event ID." -Level "INFO"
            $entryType, $mappedEventID = switch ($Level.ToUpper()) {
                'DEBUG' { 'Information', 1001 }
                'INFO' { 'Information', 1002 }
                'NOTICE' { 'Information', 1003 }
                'WARNING' { 'Warning', 2001 }
                'ERROR' { 'Error', 3001 }
                'CRITICAL' { 'Error', 3002 }
                'IMPORTANT' { 'Information', 1004 }
                'OUTPUT' { 'Information', 1005 }
                'SIGNIFICANT' { 'Information', 1006 }
                'VERYVERBOSE' { 'Information', 1007 }
                'VERBOSE' { 'Information', 1008 }
                'SOMEWHATVERBOSE' { 'Information', 1009 }
                'SYSTEM' { 'Information', 1010 }
                'INTERNALCOMMENT' { 'Information', 1011 }
                default { 'Information', 9999 }
            }
            Write-EnhancedLog -Message "Log level '$Level' mapped to entry type '$entryType' and event ID '$mappedEventID'." -Level "INFO"

            # Use provided EventID if specified, otherwise use mapped EventID
            $eventID = if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('EventID')) { $EventID } else { $mappedEventID }
            Write-EnhancedLog -Message "Using Event ID: $eventID" -Level "INFO"

            # Ensure the event log and source are initialized
            Write-EnhancedLog -Message "Initializing event log for source '$callerFunction'." -Level "INFO"

            $DBG
            try {
                Write-EnhancedLog -Message "Calling Initialize-EventLog function with SourceName: '$callerFunction'." -Level "INFO"
                $global:sanitizedlogName = Initialize-EventLog -SourceName $callerFunction -ParentScriptName $ParentScriptName
                Write-EnhancedLog -Message "Event log initialized with name '$global:sanitizedlogName'." -Level "INFO"
            
                # Sanitize the log name
                Write-EnhancedLog -Message "Sanitizing the log name for source '$callerFunction'." -Level "INFO"
                $global:sanitizedlogName = Sanitize-LogName -LogName $global:sanitizedlogName
                Write-EnhancedLog -Message "Sanitized log name: '$global:sanitizedlogName'." -Level "INFO"
            
                $DBG
            }
            catch {
                Write-EnhancedLog -Message "Failed to initialize or sanitize event log for source '$callerFunction': $($_.Exception.Message)" -Level "ERROR"
                Handle-Error -ErrorRecord $_
                throw $_
            }
            
            $DBG

            # Validate the log name before writing to the event log
            if (-not $global:sanitizedlogName -or $global:sanitizedlogName -is [System.Collections.Hashtable]) {
                Write-EnhancedLog -Message "The log name '$global:sanitizedlogName' is invalid or is a hashtable. Halting operation." -Level "CRITICAL"
                throw "Invalid log name: '$global:sanitizedlogName'"
            }

            $DBG

            # Write the message to the specified event log
            try {
                Write-EnhancedLog -Message "Validating if the event log source '$global:sanitizedsourceName' exists in log '$global:sanitizedlogName'." -Level "INFO"
                
                # Check if the source exists and count occurrences
          
            
                try {
                    # Check if the source exists and count occurrences
                    Write-EnhancedLog -Message "Checking if event log source '$global:sanitizedsourceName' exists in log '$global:sanitizedlogName'." -Level "INFO"
                    
                    $sourceExists = [System.Diagnostics.EventLog]::SourceExists("$global:sanitizedsourceName")
                    
                    if ($sourceExists) {
                        Write-EnhancedLog -Message "Event log source '$global:sanitizedsourceName' exists. Retrieving log name associated with the source." -Level "INFO"
                        
                        try {
                            $sourceLogName = [System.Diagnostics.EventLog]::LogNameFromSourceName("$global:sanitizedsourceName", ".")
                            Write-EnhancedLog -Message "Associated log name retrieved: '$sourceLogName'." -Level "INFO"
                            
                            try {
                                # Count occurrences of the source in the log
                                $sourceCount = @(Get-EventLog -LogName $sourceLogName -Source "$global:sanitizedsourceName").Count
                            
                                if ($sourceCount -eq 0) {
                                    Write-EnhancedLog -Message "No previous events found for source '$global:sanitizedsourceName' in log '$sourceLogName'. This is the first event being logged for this source." -Level "INFO"
                                }
                                else {
                                    Write-EnhancedLog -Message "Number of occurrences for source '$global:sanitizedsourceName' in log '$sourceLogName': $sourceCount." -Level "INFO"
                                }
                            }
                            catch {
                                Write-EnhancedLog -Message "Failed to count occurrences of source '$global:sanitizedsourceName' in log '$sourceLogName': $($_.Exception.Message)" -Level "ERROR"
                            
                                # Additional enhanced error handling for specific scenarios
                                if ($_.Exception.Message -match "No matches found") {
                                    Write-EnhancedLog -Message "This is expected behavior if the log source '$global:sanitizedsourceName' is being used for the first time. No prior events are logged under this source." -Level "NOTICE"
                                }
                                else {
                                    throw $_  # Re-throw the error for further handling upstream if it's not an expected case.
                                }
                            }
                            
                            
                        }
                        catch {
                            Write-EnhancedLog -Message "Failed to retrieve the log name associated with the source '$global:sanitizedsourceName': $($_.Exception.Message)" -Level "ERROR"
                            throw $_
                        }
                    }
                    else {
                        Write-EnhancedLog -Message "Event log source '$global:sanitizedsourceName' does not exist in log '$global:sanitizedlogName'. Proceeding to create it." -Level "WARNING"
                    }
                }
                catch {
                    Write-EnhancedLog -Message "An error occurred while checking or counting occurrences of the event log source '$global:sanitizedsourceName': $($_.Exception.Message)" -Level "ERROR"
                    Handle-Error -ErrorRecord $_
                    throw $_
                }
                

                $DBG
                Write-EnhancedLog -Message "Writing log message to event log '$global:sanitizedlogName' for source '$global:sanitizedsourceName'." -Level "INFO"
                Write-EventLog -LogName $global:sanitizedlogName -Source "$global:sanitizedsourceName" -EntryType $entryType -EventId $eventID -Message $Message
                Write-Host "Logged message to '$global:sanitizedlogName' from source '$global:sanitizedsourceName'"
            }
            catch {
                Write-EnhancedLog -Message "Failed to write log message to event log '$global:sanitizedlogName' for source '$global:sanitizedsourceName': $($_.Exception.Message)" -Level "ERROR"
                throw $_
            }
            

            $DBG
        }
        catch {
            Write-EnhancedLog -Message "An error occurred in Write-LogMessage function: $($_.Exception.Message)" -Level "ERROR"
            Handle-Error -ErrorRecord $_
            throw $_
        }
    }

    End {
        Write-EnhancedLog -Message "Exiting Write-LogMessage function" -Level "NOTICE"
    }
}
#EndRegion '.\Public\Write-LogMessage.ps1' 851