<# 
.SYNOPSIS
    Core logging utilities for SAMY.

.DESCRIPTION
    Provides:
      - Write-LogHelper  : standalone logger with console, file, and Event Log support.
      - Write-LogHybrid  : wrapper that prefers toolkit Write-Log if present, else falls back.

    This module is loaded first so that other subsystems can safely call Write-LogHybrid.
#>

# Ensure global log structures exist
if (-not $Global:LogCache -or -not ($Global:LogCache -is [System.Collections.ArrayList])) {
    $Global:LogCache = [System.Collections.ArrayList]::new()
}

if (-not $Global:EventSourceInitState) {
    $Global:EventSourceInitState = @{}
}

function Write-LogHelper {
    <#
    .SYNOPSIS
        Standardized logging utility with console/file output and Windows Event Log support.

    .DESCRIPTION
        Mirrors the SVSMSP toolkit Write-Log so that Write-LogHybrid can safely fall back
        when the module is not loaded.

    .NOTES
        Default EventLog : SVSMSP Events
        Default Source   : SVSMSP_Module
    #>
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$Message,

        [ValidateSet("Info", "Warning", "Error", "Success", "General")]
        [string]$Level = "Info",

        [string]$TaskCategory = "GeneralTask",

        [switch]$LogToEvent = $false,

        [string]$EventSource = "SAMY",

        [string]$EventLog = "SVSMSP Events",

        [int]$CustomEventID,

        [string]$LogFile,

        [switch]$PassThru
    )

    # Event ID and console color
    $EventID = if ($CustomEventID) { $CustomEventID } else {
        switch ($Level) {
            "Info"    { 1000 }
            "Warning" { 2000 }
            "Error"   { 3000 }
            "Success" { 4000 }
            default   { 1000 }
        }
    }

    $Color = switch ($Level) {
        "Info"    { "Cyan" }
        "Warning" { "Yellow" }
        "Error"   { "Red" }
        "Success" { "Green" }
        default   { "White" }
    }

    $FormattedMessage = "[{0}] [{1}] {2} (Event ID: {3})" -f $Level, $TaskCategory, $Message, $EventID
    Write-Host $FormattedMessage -ForegroundColor $Color

    # In-memory cache
    if (-not $Global:LogCache -or -not ($Global:LogCache -is [System.Collections.ArrayList])) {
        $Global:LogCache = [System.Collections.ArrayList]::new()
    }

    $logEntry = [PSCustomObject]@{
        Timestamp = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
        Level     = $Level
        Message   = $FormattedMessage
    }
    [void]$Global:LogCache.Add($logEntry)

    # Optional file output
    if ($LogFile) {
        try {
            "{0} {1}" -f $logEntry.Timestamp, $FormattedMessage |
                Out-File -FilePath $LogFile -Append -Encoding UTF8
        }
        catch {
            Write-Host "[Warning] Failed to write to log file: $($_.Exception.Message)" -ForegroundColor Yellow
        }
    }

    # Windows Event Log (with one-time init)
    if ($LogToEvent) {
        if (-not $Global:EventSourceInitState) {
            $Global:EventSourceInitState = @{}
        }

        $EntryType = switch ($Level) {
            "Info"    { "Information" }
            "Warning" { "Warning" }
            "Error"   { "Error" }
            "Success" { "Information" }
            default   { "Information" }
        }

        $sourceKey = "{0}|{1}" -f $EventLog, $EventSource

        if (-not $Global:EventSourceInitState.ContainsKey($sourceKey) -or
            -not $Global:EventSourceInitState[$sourceKey]) {

            try {
                if (-not [System.Diagnostics.EventLog]::SourceExists($EventSource)) {

                    # Check if current token is admin
                    $isAdmin = $false
                    try {
                        $current   = [Security.Principal.WindowsIdentity]::GetCurrent()
                        $principal = New-Object Security.Principal.WindowsPrincipal($current)
                        $isAdmin   = $principal.IsInRole(
                            [Security.Principal.WindowsBuiltInRole]::Administrator
                        )
                    }
                    catch {
                        $isAdmin = $false
                    }

                    if ($isAdmin) {
                        New-EventLog -LogName $EventLog -Source $EventSource -ErrorAction Stop
                    }
                    else {
                        $helperScript = @"
if (-not [System.Diagnostics.EventLog]::SourceExists('$EventSource')) {
    New-EventLog -LogName '$EventLog' -Source '$EventSource'
}
"@

                        $tempPath = [System.IO.Path]::Combine(
                            $env:TEMP,
                            ("Init_{0}_{1}.ps1" -f $EventLog, $EventSource).Replace(' ', '_')
                        )

                        $helperScript | Set-Content -Path $tempPath -Encoding UTF8

                        try {
                            $null = Start-Process -FilePath "powershell.exe" `
                                -ArgumentList "-ExecutionPolicy Bypass -File `"$tempPath`"" `
                                -Verb RunAs -Wait -PassThru
                        }
                        catch {
                            Write-Host "[Warning] Auto-elevation to create Event Log '$EventLog' / source '$EventSource' failed: $($_.Exception.Message)" -ForegroundColor Yellow
                        }
                        finally {
                            Remove-Item -Path $tempPath -ErrorAction SilentlyContinue
                        }
                    }
                }

                if ([System.Diagnostics.EventLog]::SourceExists($EventSource)) {
                    $Global:EventSourceInitState[$sourceKey] = $true
                }
                else {
                    $Global:EventSourceInitState[$sourceKey] = $false
                    Write-Host "[Warning] Event source '$EventSource' does not exist and could not be created. Skipping Event Log write." -ForegroundColor Yellow
                }
            }
            catch {
                Write-Host "[Warning] Failed to initialize Event Log '$EventLog' / source '$EventSource': $($_.Exception.Message)" -ForegroundColor Yellow
                $Global:EventSourceInitState[$sourceKey] = $false
            }
        }

        if ($Global:EventSourceInitState[$sourceKey]) {
            try {
                $EventMessage = "TaskCategory: {0} | Message: {1}" -f $TaskCategory, $Message
                Write-EventLog -LogName $EventLog -Source $EventSource -EntryType $EntryType -EventId $EventID -Message $EventMessage
            }
            catch {
                Write-Host "[Warning] Failed to write to Event Log: $($_.Exception.Message)" -ForegroundColor Yellow
            }
        }
    }

    if ($PassThru) {
        return $logEntry
    }
}

function Write-LogHybrid {
    <#
    .SYNOPSIS
        Wrapper that prefers SVSMSP Write-Log if available, else falls back to Write-LogHelper.
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Message,

        [ValidateSet("Info", "Warning", "Error", "Success", "General")]
        [string]$Level = "Info",

        [string]$TaskCategory = "GeneralTask",

        [switch]$LogToEvent,

        [string]$EventSource = "SVSMSP_Module",

        [string]$EventLog = "SVSMSP Events",

        [int]$CustomEventID,

        [string]$LogFile,

        [switch]$PassThru,

        [ValidateSet("Black","DarkGray","Gray","White","Red","Green","Blue","Yellow","Magenta","Cyan")]
        [string]$ForegroundColorOverride
    )

    $formatted = "[{0}] [{1}] {2}" -f $Level, $TaskCategory, $Message

    $invokeParams = @{
        Message      = $Message
        Level        = $Level
        TaskCategory = $TaskCategory
        LogToEvent   = $LogToEvent
        EventSource  = $EventSource
        EventLog     = $EventLog
    }

    if ($PSBoundParameters.ContainsKey('CustomEventID')) {
        $invokeParams.CustomEventID = $CustomEventID
    }
    if ($PSBoundParameters.ContainsKey('LogFile')) {
        $invokeParams.LogFile = $LogFile
    }
    if ($PassThru) {
        $invokeParams.PassThru = $true
    }

    if ($PSBoundParameters.ContainsKey('ForegroundColorOverride')) {
        Write-Host $formatted -ForegroundColor $ForegroundColorOverride

        if (Get-Command Write-Log -ErrorAction SilentlyContinue) {
            Write-Log @invokeParams
        }
        else {
            Write-LogHelper @invokeParams
        }
    }
    else {
        if (Get-Command Write-Log -ErrorAction SilentlyContinue) {
            Write-Log @invokeParams
        }
        else {
            Write-LogHelper @invokeParams
        }
    }
}
