#!/usr/bin/env pwsh
# =============================================================================
# Test: pane split dimension limits & prompt verification
# Verifies that:
# 1. Creating splits doesn't crash the server (was crashing after ~6 splits)
# 2. The server returns an error when panes are too small to split
# 3. Every NEW pane gets a real pwsh prompt (PS C:\), verified by capture-pane
# 4. Pane count actually increases after each successful split
# 5. All pane dimensions stay >= 2x2 (ConPTY safety)
# =============================================================================

$ErrorActionPreference = 'Continue'
$PSMUX = (Resolve-Path "$PSScriptRoot\..\target\release\psmux.exe" -ErrorAction SilentlyContinue).Path
if (-not $PSMUX) { $PSMUX = (Resolve-Path "$PSScriptRoot\..\target\release\tmux.exe" -ErrorAction SilentlyContinue).Path }
if (-not $PSMUX) { Write-Error "psmux binary not found"; exit 1 }

$totalTests  = 0
$passedTests = 0
$failedTests = 0
$failures    = @()

function Log  { param([string]$msg) Write-Host "[$(Get-Date -Format 'HH:mm:ss.fff')] $msg" }
function Pass { param([string]$name, [string]$detail)
    $script:totalTests++; $script:passedTests++
    Write-Host "  [PASS] $name - $detail" -ForegroundColor Green
}
function Fail { param([string]$name, [string]$detail)
    $script:totalTests++; $script:failedTests++
    $script:failures += "$name : $detail"
    Write-Host "  [FAIL] $name - $detail" -ForegroundColor Red
}

function Cleanup {
    try { & $PSMUX kill-server 2>&1 | Out-Null } catch {}
    Start-Sleep -Seconds 1
    try { Get-Process psmux -ErrorAction SilentlyContinue | Stop-Process -Force } catch {}
    try { Get-Process tmux  -ErrorAction SilentlyContinue | Stop-Process -Force } catch {}
    try { Get-Process pmux  -ErrorAction SilentlyContinue | Stop-Process -Force } catch {}
    Start-Sleep -Milliseconds 500
}

function Get-PaneCount {
    param([string]$Session)
    $panes = & $PSMUX list-panes -t $Session 2>&1 | Out-String
    $lines = ($panes -split "`n") | Where-Object { $_ -match '\S' }
    return $lines.Count
}

function Wait-Prompt {
    param([string]$Target, [int]$Timeout = 15000, [switch]$Relaxed)
    $sw = [System.Diagnostics.Stopwatch]::StartNew()
    while ($sw.ElapsedMilliseconds -lt $Timeout) {
        try {
            $cap = & $PSMUX capture-pane -t $Target -p 2>&1 | Out-String
            if ($cap -match "PS [A-Z]:\\") {
                return @{ Found = $true; ElapsedMs = $sw.ElapsedMilliseconds; Output = $cap }
            }
            # In very small panes the "PS " prefix wraps off screen; accept a trailing ">"
            if ($Relaxed -and $cap -match ">\s*$") {
                return @{ Found = $true; ElapsedMs = $sw.ElapsedMilliseconds; Output = $cap }
            }
        } catch {}
        Start-Sleep -Milliseconds 200
    }
    $finalCap = ""
    try { $finalCap = & $PSMUX capture-pane -t $Target -p 2>&1 | Out-String } catch {}
    return @{ Found = $false; ElapsedMs = $sw.ElapsedMilliseconds; Output = $finalCap }
}

function Check-ServerAlive {
    param([string]$Session)
    & $PSMUX has-session -t $Session 2>&1 | Out-Null
    return $LASTEXITCODE -eq 0
}

# Send a command into a pane via send-keys, wait, then capture-pane and check
# that the expected output string appears in the pane content.
function Run-And-Verify {
    param(
        [string]$Target,       # e.g. "split4:1.2"
        [string]$Command,      # e.g. "echo HELLO_MARKER"
        [string]$Expected,     # regex to match in captured output, e.g. "HELLO_MARKER"
        [int]$Timeout = 10000
    )
    # Send the command + Enter
    & $PSMUX send-keys -t $Target "$Command" Enter 2>&1 | Out-Null
    # Poll capture-pane until the expected output appears
    $sw = [System.Diagnostics.Stopwatch]::StartNew()
    while ($sw.ElapsedMilliseconds -lt $Timeout) {
        Start-Sleep -Milliseconds 300
        try {
            $cap = & $PSMUX capture-pane -t $Target -p 2>&1 | Out-String
            if ($cap -match $Expected) {
                return @{ Found = $true; ElapsedMs = $sw.ElapsedMilliseconds; Output = $cap }
            }
        } catch {}
    }
    $finalCap = ""
    try { $finalCap = & $PSMUX capture-pane -t $Target -p 2>&1 | Out-String } catch {}
    return @{ Found = $false; ElapsedMs = $sw.ElapsedMilliseconds; Output = $finalCap }
}

Log "Using: $PSMUX"
Write-Host ""

# =============================================================================
# TEST 1: Repeated vertical splits — verify each NEW pane
# =============================================================================
Write-Host ("=" * 60)
Log "TEST 1: Repeated vertical splits - verify NEW pane creation"
Write-Host ("=" * 60)
Cleanup

& $PSMUX new-session -d -s split1 2>&1 | Out-Null
Start-Sleep -Seconds 3

$r = Wait-Prompt "split1:0"
if ($r.Found) { Pass "Initial prompt" "$($r.ElapsedMs)ms" }
else          { Fail "Initial prompt" "No PS prompt in initial window" }

$maxSplits = 15
$successfulSplits = 0
$refusedSplits = 0
for ($i = 1; $i -le $maxSplits; $i++) {
    $panesBefore = Get-PaneCount "split1"
    $out = & $PSMUX split-window -t split1 -v 2>&1 | Out-String
    Start-Sleep -Milliseconds 500

    if (-not (Check-ServerAlive "split1")) {
        Fail "Server alive (vsplit $i)" "SERVER CRASHED after vsplit $i!"
        break
    }

    $panesAfter = Get-PaneCount "split1"

    # Check: did the server return an error?
    if ($out -match "too small|error|no space") {
        $refusedSplits++
        # Verify pane count did NOT increase
        if ($panesAfter -eq $panesBefore) {
            Pass "Vsplit $i refused" "correctly refused ($($out.Trim())), panes=$panesAfter"
        } else {
            Fail "Vsplit $i refused but created" "error returned but pane count went $panesBefore -> $panesAfter"
        }
        continue
    }

    # No error - split should have succeeded
    if ($panesAfter -le $panesBefore) {
        Fail "Vsplit $i no new pane" "no error but pane count unchanged ($panesBefore -> $panesAfter)"
        continue
    }

    $successfulSplits++
    $newPaneIdx = $panesAfter - 1

    # KEY CHECK: verify the NEW pane has a PS prompt
    $r = Wait-Prompt "split1:0.$newPaneIdx"
    if ($r.Found) {
        Pass "Vsplit $i new pane prompt" "pane $newPaneIdx prompt in $($r.ElapsedMs)ms (panes=$panesAfter)"
    } else {
        # Also check if any pane has the prompt — maybe active pane changed
        $anyPrompt = $false
        for ($p = 0; $p -lt $panesAfter; $p++) {
            $rc = Wait-Prompt "split1:0.$p" 3000
            if ($rc.Found -and $p -eq $newPaneIdx) { $anyPrompt = $true; break }
        }
        if ($anyPrompt) {
            Pass "Vsplit $i new pane prompt (retry)" "pane $newPaneIdx found on retry"
        } else {
            Fail "Vsplit $i new pane prompt" "pane $newPaneIdx has NO PS prompt (output: $($r.Output.Substring(0, [Math]::Min(80, $r.Output.Length))))"
        }
    }
}

if (Check-ServerAlive "split1") {
    Pass "Server survived vsplits" "$successfulSplits created, $refusedSplits refused"
} else {
    Fail "Server survived vsplits" "Server died"
}

# =============================================================================
# TEST 2: Repeated horizontal splits
# =============================================================================
Write-Host ""
Write-Host ("=" * 60)
Log "TEST 2: Repeated horizontal splits - verify NEW pane creation"
Write-Host ("=" * 60)
Cleanup

& $PSMUX new-session -d -s split2 2>&1 | Out-Null
Start-Sleep -Seconds 3

$r = Wait-Prompt "split2:0"
if ($r.Found) { Pass "Initial prompt (hsplit)" "$($r.ElapsedMs)ms" }
else          { Fail "Initial prompt (hsplit)" "No PS prompt" }

$successfulSplits = 0
$refusedSplits = 0
for ($i = 1; $i -le $maxSplits; $i++) {
    $panesBefore = Get-PaneCount "split2"
    $out = & $PSMUX split-window -t split2 -h 2>&1 | Out-String
    Start-Sleep -Milliseconds 500

    if (-not (Check-ServerAlive "split2")) {
        Fail "Server alive (hsplit $i)" "SERVER CRASHED!"
        break
    }

    $panesAfter = Get-PaneCount "split2"

    if ($out -match "too small|error|no space") {
        $refusedSplits++
        if ($panesAfter -eq $panesBefore) {
            Pass "Hsplit $i refused" "correctly refused, panes=$panesAfter"
        } else {
            Fail "Hsplit $i refused but created" "error but panes $panesBefore -> $panesAfter"
        }
        continue
    }

    if ($panesAfter -le $panesBefore) {
        Fail "Hsplit $i no new pane" "no error but panes unchanged ($panesBefore -> $panesAfter)"
        continue
    }

    $successfulSplits++
    $newPaneIdx = $panesAfter - 1

    $r = Wait-Prompt "split2:0.$newPaneIdx"
    if ($r.Found) {
        Pass "Hsplit $i new pane prompt" "pane $newPaneIdx in $($r.ElapsedMs)ms (panes=$panesAfter)"
    } else {
        Fail "Hsplit $i new pane prompt" "pane $newPaneIdx has NO PS prompt"
    }
}

if (Check-ServerAlive "split2") {
    Pass "Server survived hsplits" "$successfulSplits created, $refusedSplits refused"
} else {
    Fail "Server survived hsplits" "Server died"
}

# =============================================================================
# TEST 3: Alternating V/H splits (most realistic user scenario)
# =============================================================================
Write-Host ""
Write-Host ("=" * 60)
Log "TEST 3: Alternating V/H splits - verify every new pane"
Write-Host ("=" * 60)
Cleanup

& $PSMUX new-session -d -s split3 2>&1 | Out-Null
Start-Sleep -Seconds 3

$r = Wait-Prompt "split3:0"
if ($r.Found) { Pass "Initial prompt (alt)" "$($r.ElapsedMs)ms" }
else          { Fail "Initial prompt (alt)" "No PS prompt" }

$successfulSplits = 0
$refusedSplits = 0
for ($i = 1; $i -le 20; $i++) {
    $dir = if ($i % 2 -eq 1) { "-v" } else { "-h" }
    $dirName = if ($i % 2 -eq 1) { "V" } else { "H" }
    $panesBefore = Get-PaneCount "split3"
    $out = & $PSMUX split-window -t split3 $dir 2>&1 | Out-String
    Start-Sleep -Milliseconds 500

    if (-not (Check-ServerAlive "split3")) {
        Fail "Server alive (alt split $i $dirName)" "SERVER CRASHED!"
        break
    }

    $panesAfter = Get-PaneCount "split3"

    if ($out -match "too small|error|no space") {
        $refusedSplits++
        if ($panesAfter -eq $panesBefore) {
            Pass "AltSplit $i ($dirName) refused" "correctly refused, panes=$panesAfter"
        } else {
            Fail "AltSplit $i ($dirName) refused but created" "error but panes changed"
        }
        continue
    }

    if ($panesAfter -le $panesBefore) {
        Fail "AltSplit $i ($dirName) no new pane" "no error but panes unchanged"
        continue
    }

    $successfulSplits++
    $newPaneIdx = $panesAfter - 1

    # Later panes are very small; give extra time for shell startup
    # Panes at index >= 5 are tiny (< 15 cols); "PS " wraps off screen so use relaxed matching
    $promptTimeout = if ($newPaneIdx -ge 5) { 25000 } else { 15000 }
    $useRelaxed = $newPaneIdx -ge 5
    $r = Wait-Prompt "split3:0.$newPaneIdx" $promptTimeout -Relaxed:$useRelaxed
    if ($r.Found) {
        Pass "AltSplit $i ($dirName) new pane prompt" "pane $newPaneIdx in $($r.ElapsedMs)ms (panes=$panesAfter)"
    } else {
        Fail "AltSplit $i ($dirName) new pane prompt" "pane $newPaneIdx no prompt"
    }
}

if (Check-ServerAlive "split3") {
    Pass "Server survived alt splits" "$successfulSplits created, $refusedSplits refused"
} else {
    Fail "Server survived alt splits" "Server died"
}

# =============================================================================
# TEST 4: Multiple windows + splits (the user's exact scenario)
# =============================================================================
Write-Host ""
Write-Host ("=" * 60)
Log "TEST 4: 5 windows x 3 splits each - verify every new pane"
Write-Host ("=" * 60)
Cleanup

& $PSMUX new-session -d -s split4 2>&1 | Out-Null
Start-Sleep -Seconds 3

$r = Wait-Prompt "split4:0"
if ($r.Found) { Pass "Initial prompt (multi)" "$($r.ElapsedMs)ms" }
else          { Fail "Initial prompt (multi)" "No PS prompt" }

$totalPanes = 1
$totalRefused = 0
for ($w = 1; $w -le 4; $w++) {
    & $PSMUX new-window -t split4 2>&1 | Out-Null
    Start-Sleep -Milliseconds 1000

    if (-not (Check-ServerAlive "split4")) {
        Fail "Server alive (window $w)" "SERVER CRASHED creating window!"
        break
    }

    $r = Wait-Prompt "split4:$w"
    if ($r.Found) {
        Pass "Window $w prompt" "$($r.ElapsedMs)ms"
        $totalPanes++
    } else {
        Fail "Window $w prompt" "No prompt"
    }

    for ($s = 1; $s -le 3; $s++) {
        $dir = if ($s % 2 -eq 1) { "-v" } else { "-h" }
        $panesBefore = Get-PaneCount "split4"
        $out = & $PSMUX split-window -t split4 $dir 2>&1 | Out-String
        Start-Sleep -Milliseconds 500

        if (-not (Check-ServerAlive "split4")) {
            Fail "Server alive (win $w split $s)" "SERVER CRASHED!"
            break
        }

        $panesAfter = Get-PaneCount "split4"

        if ($out -match "too small|error|no space") {
            $totalRefused++
            Log "  Win $w split $s refused (expected)"
            continue
        }

        if ($panesAfter -le $panesBefore) {
            Fail "Win$w Split$s no new pane" "no error but panes unchanged"
            continue
        }

        $totalPanes++
        $newPaneIdx = $panesAfter - 1

        $r = Wait-Prompt "split4:$w.$newPaneIdx"
        if ($r.Found) {
            Pass "Win$w Split$s new pane prompt" "pane $newPaneIdx in $($r.ElapsedMs)ms"
        } else {
            Fail "Win$w Split$s new pane prompt" "pane $newPaneIdx has no prompt"
        }
    }
}

if (Check-ServerAlive "split4") {
    Pass "Server survived multi-window" "$totalPanes panes created, $totalRefused refused"
} else {
    Fail "Server survived multi-window" "Server died"
}

# =============================================================================
# TEST 5: Verify all pane dimensions are >= 2x2 (ConPTY safety)
# =============================================================================
Write-Host ""
Write-Host ("=" * 60)
Log "TEST 5: Verify all pane dimensions >= 2x2"
Write-Host ("=" * 60)

if (Check-ServerAlive "split4") {
    for ($w = 0; $w -le 4; $w++) {
        & $PSMUX select-window -t "split4:$w" 2>&1 | Out-Null
        Start-Sleep -Milliseconds 300
        $panes = & $PSMUX list-panes -t split4 2>&1 | Out-String
        $paneLines = ($panes -split "`n") | Where-Object { $_ -match '\S' }
        foreach ($line in $paneLines) {
            if ($line -match '\[(\d+)x(\d+)\]') {
                $cols = [int]$Matches[1]
                $rows = [int]$Matches[2]
                if ($cols -lt 2 -or $rows -lt 2) {
                    Fail "Pane dim win$w" "DANGEROUS dimensions: ${cols}x${rows} - ConPTY will crash! ($line)"
                } else {
                    Pass "Pane dim win$w" "${cols}x${rows}"
                }
            }
        }
    }
} else {
    Fail "Dimension check" "Server not alive"
}

# =============================================================================
# TEST 6: Verify exit code on refused split
# =============================================================================
Write-Host ""
Write-Host ("=" * 60)
Log "TEST 6: Exit code on refused split"
Write-Host ("=" * 60)

if (Check-ServerAlive "split4") {
    # Try to split a pane that should be too small (window 0 has been split multiple times)
    & $PSMUX select-window -t "split4:0" 2>&1 | Out-Null
    Start-Sleep -Milliseconds 300
    # Try to split the already-split panes — at least one should be too small
    # Force split into a pane we know is already at minimum
    $out = & $PSMUX split-window -t split4 -v 2>&1 | Out-String
    $exitCode = $LASTEXITCODE
    if ($out -match "too small") {
        if ($exitCode -ne 0) {
            Pass "Exit code on refuse" "exit=$exitCode, got error: $($out.Trim())"
        } else {
            Pass "Exit code on refuse" "exit=$exitCode (0 is acceptable), error: $($out.Trim())"
        }
    } else {
        # Split might have succeeded if there's still room
        Pass "Exit code test" "split succeeded (pane had room), exit=$exitCode"
    }
} else {
    Fail "Exit code test" "Server not alive"
}

# =============================================================================
# TEST 7: Run commands in every pane and verify output
# Creates a fresh session with 3 windows × 2 splits, then sends echo + ls
# into every single pane and verifies the output appeared via capture-pane.
# =============================================================================
Write-Host ""
Write-Host ("=" * 60)
Log "TEST 7: Run commands in every pane and verify output"
Write-Host ("=" * 60)
Cleanup

& $PSMUX new-session -d -s cmdtest 2>&1 | Out-Null
Start-Sleep -Seconds 3

$r = Wait-Prompt "cmdtest:0"
if ($r.Found) { Pass "Cmdtest initial prompt" "$($r.ElapsedMs)ms" }
else          { Fail "Cmdtest initial prompt" "No PS prompt" }

# Create 2 more windows, each with 2 splits (V then H) = 3 panes per window
for ($w = 1; $w -le 2; $w++) {
    & $PSMUX new-window -t cmdtest 2>&1 | Out-Null
    Start-Sleep -Milliseconds 1000
    $r = Wait-Prompt "cmdtest:$w"
    if (-not $r.Found) { Fail "Cmdtest window $w prompt" "No prompt"; continue }

    & $PSMUX split-window -t cmdtest -v 2>&1 | Out-Null
    Start-Sleep -Milliseconds 500
    & $PSMUX split-window -t cmdtest -h 2>&1 | Out-Null
    Start-Sleep -Milliseconds 500
}

# Also split the first window
& $PSMUX select-window -t "cmdtest:0" 2>&1 | Out-Null
Start-Sleep -Milliseconds 300
& $PSMUX split-window -t cmdtest -v 2>&1 | Out-Null
Start-Sleep -Milliseconds 500

# Wait for all panes to settle
Start-Sleep -Seconds 2

# Now iterate every window and every pane, run two commands:
# 1) echo MARKER_<win>_<pane>  — verify the unique marker appears
# 2) Get-ChildItem env:COMPUTERNAME — verify ls-like command works
for ($w = 0; $w -le 2; $w++) {
    & $PSMUX select-window -t "cmdtest:$w" 2>&1 | Out-Null
    Start-Sleep -Milliseconds 300

    $paneCount = Get-PaneCount "cmdtest"
    for ($p = 0; $p -lt $paneCount; $p++) {
        $target = "cmdtest:$w.$p"
        $marker = "PANE_OK_${w}_${p}"

        # First wait for the prompt to appear in this pane
        $pr = Wait-Prompt $target 8000
        if (-not $pr.Found) {
            Fail "Pane $target prompt" "No PS prompt before running command"
            continue
        }

        # TEST 7a: echo a unique marker and verify it appears
        $r = Run-And-Verify -Target $target -Command "echo $marker" -Expected $marker -Timeout 8000
        if ($r.Found) {
            Pass "echo in $target" "marker appeared in $($r.ElapsedMs)ms"
        } else {
            $snippet = if ($r.Output.Length -gt 80) { $r.Output.Substring(0, 80) } else { $r.Output }
            Fail "echo in $target" "marker '$marker' not found (captured: $snippet)"
        }

        # TEST 7b: run Get-ChildItem and verify directory listing output
        $r = Run-And-Verify -Target $target -Command "Get-ChildItem env:COMPUTERNAME" -Expected "COMPUTERNAME" -Timeout 8000
        if ($r.Found) {
            Pass "ls in $target" "Get-ChildItem output in $($r.ElapsedMs)ms"
        } else {
            $snippet = if ($r.Output.Length -gt 80) { $r.Output.Substring(0, 80) } else { $r.Output }
            Fail "ls in $target" "COMPUTERNAME not found (captured: $snippet)"
        }
    }
}

if (Check-ServerAlive "cmdtest") {
    Pass "Server survived cmd test" "all command executions completed"
} else {
    Fail "Server survived cmd test" "Server died"
}

# =============================================================================
# CLEANUP & SUMMARY
# =============================================================================
Write-Host ""
Cleanup

Write-Host ("=" * 60)
$color = if ($failedTests -eq 0) { "Green" } else { "Red" }
Write-Host "RESULTS: $passedTests passed, $failedTests failed, $totalTests total" -ForegroundColor $color
if ($failures.Count -gt 0) {
    Write-Host "Failures:" -ForegroundColor Red
    $failures | ForEach-Object { Write-Host "  - $_" -ForegroundColor Red }
}
Write-Host ("=" * 60)
exit $failedTests
