# Metrics Parser Module for HammerDB Benchmark Output
# Provides comprehensive parsing functions to extract performance metrics

function Parse-TPROCCMetrics {
    # Parses TPROC-C (OLTP) benchmark metrics from HammerDB output
    param([string]$Output)
    
    $metrics = @{
        virtualUsers = @()
        consolidatedNOPM = 0
        consolidatedTPM = 0
        databaseType = ""
    }
    
    # Parse each Virtual User result
    # Pattern: "Vuser X:TEST RESULT : System achieved XXXX NOPM from YYYY [Database] TPM"
    # Also supports: "Virtual User X: Test Result: System achieved XXXX NOPM from YYYY [Database] TPM"
    $vuMatches = [regex]::Matches($Output, "(?:Vuser|Virtual User)\s+(\d+):.*?TEST RESULT\s*:.*?System achieved\s+(\d+)\s+NOPM from\s+(\d+)\s+(\w+)(?:\s+SQL)?\s+TPM", [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)
    
    if ($vuMatches.Count -gt 0) {
        foreach ($match in $vuMatches) {
            $vuResult = @{
                virtualUser = [int]$match.Groups[1].Value
                nopm = [int]$match.Groups[2].Value
                tpm = [int]$match.Groups[3].Value
                database = $match.Groups[4].Value
            }
            $metrics.virtualUsers += $vuResult
            $metrics.consolidatedNOPM += $vuResult.nopm
            $metrics.consolidatedTPM += $vuResult.tpm
            
            if ([string]::IsNullOrEmpty($metrics.databaseType)) {
                $metrics.databaseType = $match.Groups[4].Value
            }
        }
    }
    
    # Add summary statistics
    if ($metrics.virtualUsers.Count -gt 0) {
        $metrics.virtualUserCount = $metrics.virtualUsers.Count
        $metrics.averageNOPM = [math]::Round($metrics.consolidatedNOPM / $metrics.virtualUsers.Count, 2)
        $metrics.averageTPM = [math]::Round($metrics.consolidatedTPM / $metrics.virtualUsers.Count, 2)
    }
    
    return $metrics
}

function Parse-TPROCHMetrics {
    # Parses TPROC-H (Analytics) benchmark metrics from HammerDB output
    param([string]$Output)
    
    $metrics = @{
        virtualUsers = @()
        geometricMeans = @()
        averageGeometricMean = 0
        queryCount = 0
    }
    
    # Parse geometric mean for each virtual user with VU number
    # Pattern: "Vuser X:Geometric mean of query times returning rows (22) is XX"
    $gmMatches = [regex]::Matches($Output, "Vuser\s+(\d+):.*?Geometric mean of query times returning rows \((\d+)\) is\s+([\d.]+)")
    
    if ($gmMatches.Count -gt 0) {
        # Group geometric means by virtual user
        $vuGroups = @{}
        
        foreach ($match in $gmMatches) {
            $vuNumber = [int]$match.Groups[1].Value
            $queryCount = [int]$match.Groups[2].Value
            $gm = [double]$match.Groups[3].Value
            
            if (-not $vuGroups.ContainsKey($vuNumber)) {
                $vuGroups[$vuNumber] = @()
            }
            $vuGroups[$vuNumber] += $gm
            $metrics.queryCount = $queryCount
        }
        
        # Calculate average geometric mean per virtual user
        foreach ($vuNumber in ($vuGroups.Keys | Sort-Object)) {
            $vuGeometricMeans = $vuGroups[$vuNumber]
            $avgGm = [math]::Round(
                ($vuGeometricMeans | Measure-Object -Average).Average,
                5
            )
            
            $metrics.virtualUsers += @{
                virtualUser = $vuNumber
                geometricMean = $avgGm
                queryCount = $metrics.queryCount
            }
            $metrics.geometricMeans += $avgGm
        }
        
        # Calculate overall average across all virtual users
        if ($metrics.geometricMeans.Count -gt 0) {
            $metrics.averageGeometricMean = [math]::Round(
                ($metrics.geometricMeans | Measure-Object -Average).Average, 
                3
            )
            $metrics.virtualUserCount = $metrics.geometricMeans.Count
        }
    }
    
    return $metrics
}

function Get-MetricsSummary {
    # Generates a human-readable summary of parsed metrics
    param(
        [hashtable]$Metrics,
        [string]$BenchmarkType
    )
    
    $nl = [Environment]::NewLine
    $summary = ""
    
    if ($BenchmarkType -eq "TPROC-C") {
        if ($Metrics.virtualUsers.Count -gt 0) {
            $summary += "TPROC-C Results:$nl"
            foreach ($vu in $Metrics.virtualUsers) {
                $summary += "  Virtual User $($vu.virtualUser): System achieved $($vu.nopm) NOPM from $($vu.tpm) $($vu.database) TPM$nl"
            }
            $summary += "$nl"
            $summary += "Consolidated: $($Metrics.consolidatedNOPM) NOPM from $($Metrics.consolidatedTPM) TPM$nl"
            $summary += "Average per VU: $($Metrics.averageNOPM) NOPM from $($Metrics.averageTPM) TPM"
        } else {
            $summary = "No TPROC-C metrics found in output"
        }
    } elseif ($BenchmarkType -eq "TPROC-H") {
        if ($Metrics.virtualUsers.Count -gt 0) {
            $summary += "TPROC-H Results:$nl"
            foreach ($vu in $Metrics.virtualUsers) {
                $summary += "  Virtual User $($vu.virtualUser): Geometric mean of query times returning rows ($($vu.queryCount)) is $($vu.geometricMean)$nl"
            }
            $summary += "$nl"
            $summary += "Average of all virtual users: $($Metrics.averageGeometricMean) seconds"
        } else {
            $summary = "No TPROC-H metrics found in output"
        }
    }
    
    return $summary
}

Export-ModuleMember -Function @(
    'Parse-TPROCCMetrics',
    'Parse-TPROCHMetrics',
    'Get-MetricsSummary'
)
