param(
  [ValidateSet("postgres","oracle")]
  [string]$Database = "postgres",
  [Parameter(Mandatory = $true)]
  [string]$DbUser,
  [Parameter(Mandatory = $true)]
  [string]$DbPass,
  [string]$DbUrl,
  [DateTime]$ScriptStartTime = (Get-Date)
)

$OracleUrl = "jdbc:oracle:thin:@//localhost:13389/ORCL"
$PgUrl = "jdbc:postgresql://172.17.0.19:5444/postgres"

$JMeter = "..\jmeter\bin\jmeter.bat"

$PgJmx = ".\Postgres-MaxUsers-DBBenchmark.jmx"
$OracleJmx = ".\Oracle-MaxUsers-DBBenchmark.jmx"
$Jmx = if ($Database -eq "oracle") { $OracleJmx } else { $PgJmx }
$LogDir = "..\logs"
$ReportDir = "..\reports"

# Create output directories if they don't exist
if (-not (Test-Path $LogDir)) {
    New-Item -ItemType Directory -Path $LogDir -Force | Out-Null
    Write-Host "Created logs directory at root level" -ForegroundColor Gray
}
if (-not (Test-Path $ReportDir)) {
    New-Item -ItemType Directory -Path $ReportDir -Force | Out-Null
    Write-Host "Created reports directory at root level" -ForegroundColor Gray
}

# Format timestamp for use in file paths (filesystem-friendly format)
$TimestampSuffix = $ScriptStartTime.ToString("yyyy-MM-dd_HH-mm-ss")
Write-Host "Script started at: $($ScriptStartTime.ToString('yyyy-MM-dd HH:mm:ss'))" -ForegroundColor Cyan

# Create timestamped folder for this test run
$TimestampedReportDir = Join-Path $ReportDir $TimestampSuffix
if (-not (Test-Path $TimestampedReportDir)) {
    New-Item -ItemType Directory -Path $TimestampedReportDir -Force | Out-Null
    Write-Host "Created timestamped report directory: $TimestampedReportDir" -ForegroundColor Gray
}

# Settings
$Users = 50
$Step  = 25
$MaxUsers = 400

# Stop criteria
$P95ThresholdMs = 10000
$ErrorRateThreshold = 5

$DefaultDbUrl = if ($Database -eq "oracle") { $OracleUrl } else { $PgUrl }
if ([string]::IsNullOrWhiteSpace($DbUrl)) {
  $DbUrl = $DefaultDbUrl
}
$DbDriver = if ($Database -eq "oracle") { "oracle.jdbc.OracleDriver" } else { "org.postgresql.Driver" }

# Verify Java is available (should be set by launcher script)
if (-not $env:JAVA_HOME) {
  Write-Host "ERROR: JAVA_HOME is not set." -ForegroundColor Red
  Write-Host "Please run this script via run.ps1 (Windows) or run.sh (Linux/Mac)" -ForegroundColor Yellow
  Write-Host ""
  exit 1
}

$javaExe = Join-Path $env:JAVA_HOME "bin\java.exe"
if (-not (Test-Path $javaExe)) {
  Write-Host "ERROR: Java executable not found at $javaExe" -ForegroundColor Red
  Write-Host "Please ensure the bundled JRE is present in the installation directory." -ForegroundColor Yellow
  Write-Host ""
  exit 1
}

# Verify it's Java 8 (JMeter 5.6.3 requires Java 8)
$javaVersionLine = (& $javaExe -version 2>&1 | Select-Object -First 1)
Write-Host "Using Java from: $env:JAVA_HOME" -ForegroundColor Cyan
Write-Host "Java version: $javaVersionLine" -ForegroundColor Cyan
Write-Host ""

$javaMatch = [regex]::Match($javaVersionLine, '"(?<ver>[^"]+)"')
if ($javaMatch.Success) {
  $ver = $javaMatch.Groups["ver"].Value
  $majorStr = if ($ver.StartsWith("1.")) { $ver.Split(".")[1] } else { $ver.Split(".")[0] }
  $major = 0
  if ([int]::TryParse($majorStr, [ref]$major) -and $major -ne 8) {
    Write-Host "WARNING: This script is designed for Java 8. Current version: $ver" -ForegroundColor Yellow
    Write-Host "JMeter may not work correctly with Java $major." -ForegroundColor Yellow
    Write-Host ""
  }
}


while ($Users -le $MaxUsers) {
  $Jtl = Join-Path $LogDir ("results_" + $Database + "_" + $Users + ".jtl")
  $Log = Join-Path $LogDir ("jmeter_" + $Database + "_" + $Users + ".log")

  Write-Host "`n=== Running $Users users ==="

  $ArgsList = @(
    "-n", "-t", $Jmx, "-l", $Jtl, "-j", $Log,
    ("-Jmax_users={0}" -f $Users), ("-Jdb_pool_max={0}" -f $Users),
    "-Jramp_seconds=60", "-Jduration_seconds=120", "-Jwork_units=8000",
    ("-Jdb_url={0}" -f $DbUrl), ("-Jdb_user={0}" -f $DbUser), ("-Jdb_password={0}" -f $DbPass),
    ("-Jdb_driver={0}" -f $DbDriver),
    ("-Jp95_threshold_ms={0}" -f $P95ThresholdMs), ("-Jerror_rate_threshold={0}" -f $ErrorRateThreshold),
    "-Jquery_timeout_seconds=10", "-Jdb_timeout_ms=10000"
  )

  & $JMeter @ArgsList

  # Generate HTML report
  if (Test-Path $Jtl) {
    $ReportFolder = Join-Path $TimestampedReportDir ("report_" + $Database + "_" + $Users)
    Write-Host "Generating HTML report..." -ForegroundColor Cyan
    $ReportArgs = @("-g", $Jtl, "-o", $ReportFolder)
    & $JMeter @ReportArgs
    Write-Host "HTML report saved to: $ReportFolder" -ForegroundColor Green
  }

  if (!(Test-Path $Jtl)) {
    Write-Host "No results file found, stopping."
    break
  }

  $rows = Import-Csv $Jtl
  $total = $rows.Count
  $errors = ($rows | Where-Object { $_.success -eq "false" }).Count
  $errorRate = if ($total -gt 0) { $errors / $total } else { 1 }

  $elapsed = $rows | ForEach-Object { [int]$_.elapsed } | Sort-Object
  $p95 = if ($elapsed.Count -gt 0) {
    $idx = [Math]::Ceiling($elapsed.Count * 0.95) - 1
    $elapsed[$idx]
  } else { 0 }

  $poolError = $rows | Where-Object {
    $_.responseMessage -like "*Error preloading the connection pool*"
  }

  Write-Host ("Users={0}  Total={1}  Errors={2}  ErrorRate={3:P2}  P95={4}ms" -f `
              $Users, $total, $errors, $errorRate, $p95)

  if ($errorRate -ge $ErrorRateThreshold -or $p95 -ge $P95ThresholdMs -or $poolError) {
    Write-Host "STOP: threshold hit at $Users users"
    break
  }

  $Users += $Step
}

# Move JMeter's default log file to logs directory if it exists (cleanup after all tests)
$DefaultJMeterLog = ".\jmeter.log"
if (Test-Path $DefaultJMeterLog) {
  $TargetLog = Join-Path $LogDir "jmeter.log"
  Move-Item -Path $DefaultJMeterLog -Destination $TargetLog -Force
}