Private/Get-CachedOutput.ps1

function Get-CachedOutput {
    <#
    .SYNOPSIS
        Retrieves cached output for a colorscript if available and valid.
    #>

    [CmdletBinding()]
    [OutputType([pscustomobject])]
    param(
        [Parameter(Mandatory)]
        [string]$ScriptPath
    )

    if ([string]::IsNullOrWhiteSpace($ScriptPath)) {
        return [pscustomobject]@{
            Available     = $false
            CacheFile     = $null
            Content       = ''
            LastWriteTime = $null
        }
    }

    if (-not $script:CacheDir) {
        try {
            Initialize-CacheDirectory
        }
        catch {
            Write-Verbose "Initialize-CacheDirectory failed: $($_.Exception.Message)"
        }
    }

    if (-not $script:CacheDir) {
        return [pscustomobject]@{
            Available     = $false
            CacheFile     = $null
            Content       = ''
            LastWriteTime = $null
        }
    }

    $scriptName = [System.IO.Path]::GetFileNameWithoutExtension($ScriptPath)
    $cacheFile = Join-Path -Path $script:CacheDir -ChildPath ("{0}.cache" -f $scriptName)
    $metadataPath = Get-CacheEntryMetadataPath -ScriptName $scriptName

    try {
        $scriptFileExists = $false
        try {
            $scriptFileExists = & $script:FileExistsDelegate $ScriptPath
        }
        catch {
            Write-Verbose "Unable to verify script existence for ${ScriptPath}: $($_.Exception.Message)"
            return [pscustomobject]@{
                Available     = $false
                CacheFile     = $null
                Content       = ''
                LastWriteTime = $null
            }
        }

        if (-not $scriptFileExists) {
            return [pscustomobject]@{
                Available     = $false
                CacheFile     = $null
                Content       = ''
                LastWriteTime = $null
            }
        }

        if (-not (Test-Path -LiteralPath $cacheFile)) {
            return [pscustomobject]@{
                Available     = $false
                CacheFile     = $cacheFile
                Content       = ''
                LastWriteTime = $null
            }
        }

        if (-not $metadataPath -or -not (Test-Path -LiteralPath $metadataPath -PathType Leaf)) {
            return [pscustomobject]@{
                Available     = $false
                CacheFile     = $cacheFile
                Content       = ''
                LastWriteTime = $null
            }
        }

        $metadata = $null
        try {
            $metadataContent = & $script:FileReadAllTextDelegate $metadataPath $script:Utf8NoBomEncoding
            if (-not [string]::IsNullOrWhiteSpace($metadataContent)) {
                $metadata = $metadataContent | ConvertFrom-Json -Depth 5
            }
        }
        catch {
            Write-Verbose ("Cache metadata read error for {0}: {1}" -f $ScriptPath, $_.Exception.Message)
            $metadata = $null
        }

        if (-not $metadata) {
            return [pscustomobject]@{
                Available     = $false
                CacheFile     = $cacheFile
                Content       = ''
                LastWriteTime = $null
            }
        }

        $metadataVersion = if ($metadata.PSObject.Properties['Version']) { [int]$metadata.Version } else { 0 }
        if ($metadataVersion -ne $script:CacheEntryMetadataVersion) {
            return [pscustomobject]@{
                Available     = $false
                CacheFile     = $cacheFile
                Content       = ''
                LastWriteTime = $null
            }
        }

        $metadataLength = if ($metadata.PSObject.Properties['ScriptLength']) { [long]$metadata.ScriptLength } else { $null }
        if ($null -eq $metadataLength) {
            return [pscustomobject]@{
                Available     = $false
                CacheFile     = $cacheFile
                Content       = ''
                LastWriteTime = $null
            }
        }

        $scriptInfo = Get-Item -LiteralPath $ScriptPath -ErrorAction Stop
        $cacheLastWrite = $null
        try {
            $cacheLastWrite = & $script:FileGetLastWriteTimeUtcDelegate $cacheFile
        }
        catch {
            $cacheLastWrite = $null
        }

        if (-not $cacheLastWrite) {
            try {
                $cacheLastWrite = [System.IO.File]::GetLastWriteTimeUtc($cacheFile)
            }
            catch {
                try {
                    $cacheLastWrite = [System.IO.File]::GetLastWriteTime($cacheFile)
                }
                catch {
                    $cacheLastWrite = $null
                }
            }
        }

        $scriptLastWriteUtc = $scriptInfo.LastWriteTimeUtc

        if ([long]$scriptInfo.Length -ne $metadataLength) {
            return [pscustomobject]@{
                Available     = $false
                CacheFile     = $cacheFile
                Content       = ''
                LastWriteTime = $cacheLastWrite
            }
        }

        $metadataLastWriteUtc = $null
        if ($metadata.PSObject.Properties['ScriptLastWriteTimeUtc'] -and $metadata.ScriptLastWriteTimeUtc) {
            try {
                $metadataLastWriteUtc = [System.DateTime]::ParseExact(
                    [string]$metadata.ScriptLastWriteTimeUtc,
                    'o',
                    [System.Globalization.CultureInfo]::InvariantCulture,
                    [System.Globalization.DateTimeStyles]::AdjustToUniversal)
            }
            catch {
                $metadataLastWriteUtc = $null
            }
        }

        $metadataHash = $null
        if ($metadata.PSObject.Properties['ScriptHash']) {
            $metadataHash = ([string]$metadata.ScriptHash)
        }

        $metadataHashAlgorithm = if ($metadata.PSObject.Properties['ScriptHashAlgorithm'] -and $metadata.ScriptHashAlgorithm) {
            [string]$metadata.ScriptHashAlgorithm
        }
        elseif ($script:CacheEntryHashAlgorithm) {
            $script:CacheEntryHashAlgorithm
        }
        else {
            'SHA256'
        }

        $cacheGeneratedUtc = if ($metadata.PSObject.Properties['CacheGeneratedUtc']) { [string]$metadata.CacheGeneratedUtc } else { $null }
        $storedModuleVersion = if ($metadata.PSObject.Properties['ModuleVersion']) { [string]$metadata.ModuleVersion } else { $null }

        $contentValidated = $false
        if ($metadataLastWriteUtc -and ($scriptLastWriteUtc -eq $metadataLastWriteUtc)) {
            $contentValidated = $true
        }
        else {
            if ([string]::IsNullOrWhiteSpace($metadataHash)) {
                return [pscustomobject]@{
                    Available     = $false
                    CacheFile     = $cacheFile
                    Content       = ''
                    LastWriteTime = $cacheLastWrite
                }
            }

            $algorithmNormalized = $metadataHashAlgorithm.ToUpperInvariant()
            if ($algorithmNormalized -ne 'SHA256') {
                return [pscustomobject]@{
                    Available     = $false
                    CacheFile     = $cacheFile
                    Content       = ''
                    LastWriteTime = $cacheLastWrite
                }
            }

            $computedSignature = $null
            try {
                $computedSignature = Get-FileContentSignature -Path $ScriptPath -IncludeHash
            }
            catch {
                Write-Verbose ("Failed to compute file signature for {0}: {1}" -f $ScriptPath, $_.Exception.Message)
                $computedSignature = $null
            }

            if (-not $computedSignature -or ([long]$computedSignature.Length -ne $metadataLength)) {
                return [pscustomobject]@{
                    Available     = $false
                    CacheFile     = $cacheFile
                    Content       = ''
                    LastWriteTime = $cacheLastWrite
                }
            }

            if ([string]::IsNullOrWhiteSpace($computedSignature.Hash)) {
                return [pscustomobject]@{
                    Available     = $false
                    CacheFile     = $cacheFile
                    Content       = ''
                    LastWriteTime = $cacheLastWrite
                }
            }

            $expectedHash = $metadataHash.ToLowerInvariant()
            $actualHash = $computedSignature.Hash.ToLowerInvariant()
            if ($expectedHash -ne $actualHash) {
                return [pscustomobject]@{
                    Available     = $false
                    CacheFile     = $cacheFile
                    Content       = ''
                    LastWriteTime = $cacheLastWrite
                }
            }

            $contentValidated = $true

            try {
                Write-CacheEntryMetadataFile -ScriptName $scriptName -Signature $computedSignature -CacheFile $cacheFile -CacheGeneratedUtc $cacheGeneratedUtc -ModuleVersionOverride $storedModuleVersion
            }
            catch {
                Write-Verbose ("Cache metadata refresh failed for {0}: {1}" -f $ScriptPath, $_.Exception.Message)
            }
        }

        if (-not $contentValidated) {
            return [pscustomobject]@{
                Available     = $false
                CacheFile     = $cacheFile
                Content       = ''
                LastWriteTime = $cacheLastWrite
            }
        }

        $content = & $script:FileReadAllTextDelegate $cacheFile $script:Utf8NoBomEncoding

        return [pscustomobject]@{
            Available     = $true
            CacheFile     = $cacheFile
            Content       = $content
            LastWriteTime = $cacheLastWrite
        }
    }
    catch {
        Write-Verbose "Cache read error for $ScriptPath : $($_.Exception.Message)"
        return [pscustomobject]@{
            Available     = $false
            CacheFile     = $cacheFile
            Content       = ''
            LastWriteTime = $null
        }
    }
}