functions/private/Invoke-UniversalSQLiteQuery.ps1

function Invoke-UniversalSQLiteQuery {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$Path,
        
        [Parameter(Mandatory)]
        [string]$Query
    )

    # Verify sqlite3 is available
    if (-not (Get-Command sqlite3 -ErrorAction SilentlyContinue)) {
        throw "sqlite3 command not found. Please install SQLite."
    }

    # Verify database exists
    if (-not (Test-Path $Path)) {
        throw "Database file not found: $Path"
    }

    # Resolve full path
    $dbPath = Resolve-Path $Path | Select-Object -ExpandProperty Path

    # Use .timeout command for sqlite3 CLI (doesn't return output, just sets connection timeout)
    # This is critical for concurrent access in web apps (5000ms = 5 seconds)
    $timeoutCmd = ".timeout 5000"
    $combinedInput = "$timeoutCmd`n$Query"

    # Try JSON output first (best for structured data)
    # Always pass via stdin to ensure .timeout command is processed first
    $output = $combinedInput | sqlite3 $dbPath -json - 2>&1

    # Check for errors
    if ($LASTEXITCODE -ne 0) {
        throw "SQLite query failed: $output"
    }

    # Parse output
    if ($output) {
        try {
            # Try to parse as JSON
            $result = $output | ConvertFrom-Json
            return $result
        }
        catch {
            # JSON parsing failed, try CSV mode for better compatibility
            $csvOutput = $combinedInput | sqlite3 $dbPath -csv -header - 2>&1

            if ($LASTEXITCODE -eq 0 -and $csvOutput) {
                try {
                    # Convert CSV to objects
                    $result = $csvOutput | ConvertFrom-Csv
                    return $result
                }
                catch {
                    # If CSV also fails, return raw output
                    return $csvOutput
                }
            }

            # Fallback to raw output
            return $output
        }
    }

    return $null
}