_TESTS/stress-benchmark.ps1

# ===========================================================================
# PSLocalBase High-Volume Multi-Operation Stress & Benchmark Test
# ===========================================================================

[CmdletBinding()]
param(
    [int]$TotalRecords = 10000
)

$ErrorActionPreference = "Stop"
$sw = [System.Diagnostics.Stopwatch]::new()

Write-Host "==========================================================" -ForegroundColor Cyan
Write-Host " PSLocalBase High-Volume Stress & Benchmark Test" -ForegroundColor Cyan
Write-Host " Target Record Count: $TotalRecords" -ForegroundColor Yellow
Write-Host " PowerShell Version: $($PSVersionTable.PSVersion)" -ForegroundColor DarkGray
Write-Host "==========================================================" -ForegroundColor Cyan

# Import Module
$modulePath = Join-Path (Split-Path $PSScriptRoot -Parent) "PSLocalBase.psd1"
Import-Module $modulePath -Force

$dbFile = Join-Path ([System.IO.Path]::GetTempPath()) "pslocalbase_stress_$([Guid]::NewGuid().ToString('N')).db"
$db = [PSLocalBase]::new($dbFile)

try {
    # -----------------------------------------------------------------------
    # 1. BULK INSERTION (10,000 complex JSON documents)
    # -----------------------------------------------------------------------
    Write-Host "`n[1/7] Bulk Inserting $TotalRecords complex documents within a transaction..." -ForegroundColor Cyan
    $departments = @("Engineering", "Finance", "HumanResources", "Sales", "Marketing", "Legal", "Operations")
    $roles = @("Junior", "Mid", "Senior", "Lead", "Manager", "Director")
    $cities = @("Madrid", "London", "New York", "Tokyo", "Berlin", "Paris", "Toronto")

    $sw.Restart()
    $db.beginTransaction()

    for ($i = 1; $i -le $TotalRecords; $i++) {
        $dept = $departments[$i % $departments.Count]
        $role = $roles[$i % $roles.Count]
        $city = $cities[$i % $cities.Count]
        $salary = 40000 + (($i * 17) % 110000)
        $active = ($i % 3 -ne 0) # ~66% active

        $db.collection("employees").doc("emp-$i").set(@{
                id         = $i
                name       = "Employee_$i"
                email      = "emp$i@enterprise.corp"
                department = $dept
                role       = $role
                salary     = $salary
                active     = $active
                profile    = @{
                    city       = $city
                    experience = ($i % 15) + 1
                }
                tags       = @("staff", $dept.ToLower(), $role.ToLower())
            })
    }

    $db.commit()
    $sw.Stop()

    $insertElapsedMs = $sw.ElapsedMilliseconds
    $insertRate = [Math]::Round($TotalRecords / ($insertElapsedMs / 1000), 2)
    Write-Host " -> Inserted $TotalRecords documents in: $insertElapsedMs ms" -ForegroundColor Green
    Write-Host " -> Throughput: $insertRate operations/sec" -ForegroundColor Green

    $dbSize = (Get-Item $dbFile).Length / 1MB
    Write-Host " -> Database File Size on disk: $([Math]::Round($dbSize, 2)) MB" -ForegroundColor DarkGray

    # -----------------------------------------------------------------------
    # 2. RANDOM POINT LOOKUPS (.doc('key').get())
    # -----------------------------------------------------------------------
    $lookupCount = 1000
    Write-Host "`n[2/7] Performing $lookupCount random point lookups by primary key..." -ForegroundColor Cyan
    $sw.Restart()

    for ($k = 0; $k -lt $lookupCount; $k++) {
        $randId = Get-Random -Minimum 1 -Maximum ($TotalRecords + 1)
        $doc = $db.collection("employees").doc("emp-$randId").get()
        if ($null -eq $doc -or $doc.id -ne $randId) {
            throw "Point lookup failed for key: emp-$randId"
        }
    }

    $sw.Stop()
    $lookupElapsedMs = $sw.ElapsedMilliseconds
    $avgLookupLatency = [Math]::Round(($lookupElapsedMs / $lookupCount), 4)
    Write-Host " -> Executed $lookupCount random lookups in: $lookupElapsedMs ms" -ForegroundColor Green
    Write-Host " -> Average Latency per lookup: $avgLookupLatency ms ($([Math]::Round(1000 / $avgLookupLatency, 2)) reads/sec)" -ForegroundColor Green

    # -----------------------------------------------------------------------
    # 3. FILTERING WITH NATIVE JSON_EXTRACT (.where(...).get())
    # -----------------------------------------------------------------------
    Write-Host "`n[3/7] Running complex JSON queries across all $TotalRecords records..." -ForegroundColor Cyan

    # Query A: Boolean filter
    $sw.Restart()
    $activeEmployees = $db.collection("employees").where("active", "=", $true).get()
    $sw.Stop()
    Write-Host " -> [Query A] Boolean active=true: Found $($activeEmployees.Count) records in $($sw.ElapsedMilliseconds) ms" -ForegroundColor Green

    # Query B: Number comparison
    $sw.Restart()
    $highEarners = $db.collection("employees").where("salary", ">=", 100000).get()
    $sw.Stop()
    Write-Host " -> [Query B] Numeric salary >= 100,000: Found $($highEarners.Count) records in $($sw.ElapsedMilliseconds) ms" -ForegroundColor Green

    # Query C: Chained multi-field filter
    $sw.Restart()
    $topEngineers = $db.collection("employees").where("department", "=", "Engineering").where("active", "=", $true).where("salary", ">=", 80000).get()
    $sw.Stop()
    Write-Host " -> [Query C] Compound filter (dept=Engineering AND active=true AND salary>=80k): Found $($topEngineers.Count) records in $($sw.ElapsedMilliseconds) ms" -ForegroundColor Green

    # Query D: IN Operator
    $sw.Restart()
    $management = $db.collection("employees").where("role", "IN", @("Lead", "Manager", "Director")).get()
    $sw.Stop()
    Write-Host " -> [Query D] IN filter (role IN ['Lead', 'Manager', 'Director']): Found $($management.Count) records in $($sw.ElapsedMilliseconds) ms" -ForegroundColor Green

    # -----------------------------------------------------------------------
    # 4. ORDER BY & PAGINATION / LIMIT
    # -----------------------------------------------------------------------
    Write-Host "`n[4/7] Testing Sorting (orderBy) and Limits..." -ForegroundColor Cyan
    $sw.Restart()
    $topPaid = $db.collection("employees").orderBy("salary", "desc").limit(5).get()
    $sw.Stop()
    Write-Host " -> Top 5 highest paid employees (retrieved in $($sw.ElapsedMilliseconds) ms):" -ForegroundColor Green
    foreach ($emp in $topPaid) {
        Write-Host " * $($emp.name) | Dept: $($emp.department) | Salary: `$$($emp.salary)" -ForegroundColor White
    }

    # -----------------------------------------------------------------------
    # 5. PARTIAL UPDATES (.update() with recursive merge)
    # -----------------------------------------------------------------------
    $updateCount = 1000
    Write-Host "`n[5/7] Executing $updateCount deep recursive partial updates..." -ForegroundColor Cyan
    $sw.Restart()
    $db.beginTransaction()

    for ($u = 1; $u -le $updateCount; $u++) {
        $db.collection("employees").doc("emp-$u").update(@{
                salary   = 150000
                promoted = $true
                profile  = @{
                    city = "Zurich" # updates city, preserves experience
                }
            })
    }

    $db.commit()
    $sw.Stop()

    $updateElapsedMs = $sw.ElapsedMilliseconds
    Write-Host " -> Updated $updateCount records in: $updateElapsedMs ms ($([Math]::Round($updateCount / ($updateElapsedMs / 1000), 2)) updates/sec)" -ForegroundColor Green

    # Verify deep merge integrity on updated record
    $checkEmp = $db.collection("employees").doc("emp-1").get()
    if ($checkEmp.salary -ne 150000 -or $checkEmp.promoted -ne $true -or $checkEmp.profile.city -ne "Zurich" -or $checkEmp.profile.experience -ne 2) {
        throw "Deep merge integrity check failed on emp-1"
    }
    Write-Host " -> Deep merge verification passed (city updated, experience preserved, non-updated fields intact)." -ForegroundColor Green

    # -----------------------------------------------------------------------
    # 6. GET WITH KEYS (.get({ keys = $true }))
    # -----------------------------------------------------------------------
    Write-Host "`n[6/7] Retrieving documents with explicit SQLite keys metadata..." -ForegroundColor Cyan
    $sw.Restart()
    $keyedSample = $db.collection("employees").limit(3).get(@{ keys = $true })
    $sw.Stop()
    Write-Host " -> Key metadata verification (retrieved in $($sw.ElapsedMilliseconds) ms):" -ForegroundColor Green
    foreach ($item in $keyedSample) {
        Write-Host " * Key: $($item.key) -> Data Name: $($item.data.name)" -ForegroundColor White
    }

    # -----------------------------------------------------------------------
    # 7. FILTERED DELETION & ATOMIC CLEANUP
    # -----------------------------------------------------------------------
    Write-Host "`n[7/7] Testing filtered and point deletions..." -ForegroundColor Cyan
    $sw.Restart()
    $db.collection("employees").where("active", "=", $false).delete()
    $sw.Stop()
    Write-Host " -> Bulk deleted all inactive employees in $($sw.ElapsedMilliseconds) ms" -ForegroundColor Green

    $remainingCount = ($db.collection("employees").get()).Count
    Write-Host " -> Remaining active employees in collection: $remainingCount" -ForegroundColor Green

}
finally {
    # Clean up database
    $db.deleteDatabase()
    Write-Host "`n[Clean Up] Database and WAL/SHM files deleted cleanly from disk." -ForegroundColor Cyan
}

Write-Host "`n==========================================================" -ForegroundColor Green
Write-Host " Stress & Benchmark Test Completed Successfully!" -ForegroundColor Green
Write-Host "==========================================================" -ForegroundColor Green