#!/usr/bin/env bash

# Test for parallel task execution reliability (GitHub issue #5451)
# This test verifies that tasks with ::: syntax run concurrently rather than sequentially

set -euo pipefail

# Create a temporary file to track task execution order and timing
temp_log=$(mktemp)
trap 'rm -f $temp_log' EXIT

cat <<EOF >mise.toml
[tools]
poetry = "latest"

[tasks.process1]
run = '''
echo "\$(date +%s%N) process1 start" >> $temp_log
sleep 2
echo "\$(date +%s%N) process1 end" >> $temp_log
echo "process1 complete"
'''

[tasks.process2]
run = '''
echo "\$(date +%s%N) process2 start" >> $temp_log
sleep 2
echo "\$(date +%s%N) process2 end" >> $temp_log
echo "process2 complete"
'''

[tasks.process3]
run = '''
echo "\$(date +%s%N) process3 start" >> $temp_log
sleep 2
echo "\$(date +%s%N) process3 end" >> $temp_log
echo "process3 complete"
'''

[tasks.process4]
run = '''
echo "\$(date +%s%N) process4 start" >> $temp_log
sleep 2
echo "\$(date +%s%N) process4 end" >> $temp_log
echo "process4 complete"
'''

[tasks.process5]
run = '''
echo "\$(date +%s%N) process5 start" >> $temp_log
sleep 2
echo "\$(date +%s%N) process5 end" >> $temp_log
echo "process5 complete"
'''

[tasks.process6]
run = '''
echo "\$(date +%s%N) process6 start" >> $temp_log
sleep 2
echo "\$(date +%s%N) process6 end" >> $temp_log
echo "process6 complete"
'''

[tasks.run-all]
run = "mise run process1 ::: process2 ::: process3 ::: process4 ::: process5 ::: process6"
EOF

assert "mise install"

echo "Testing parallel task execution (running 3 times for reliability)..."

# Run the test 3 times to ensure reliability
for test_run in {1..3}; do
  echo ""
  echo "=== Test Run $test_run/3 ==="

  # Clear the log file for each run
  rm -f "$temp_log"

  # Record start time for overall execution time measurement
  start_time=$(date +%s)

  # Run the tasks and capture output
  task_output=$(mise run run-all)

  # Record end time
  end_time=$(date +%s)
  total_time=$((end_time - start_time))

  echo "Total execution time: ${total_time}s"

  # Read the log file to analyze timing
  echo "Task execution log:"
  cat "$temp_log" | sort

  # Parse start/end times using bash3-compatible arrays (mapfile is bash4+).
  start_times=()
  while IFS= read -r ts; do
    start_times+=("$ts")
  done < <(grep "start" "$temp_log" | awk '{print $1}' | sort -n)
  end_times=()
  while IFS= read -r ts; do
    end_times+=("$ts")
  done < <(grep "end" "$temp_log" | awk '{print $1}' | sort -n)

  echo "Analyzing task start times..."

  if [ ${#start_times[@]} -ne 6 ]; then
    echo "ERROR: Expected 6 task start times, got ${#start_times[@]}"
    exit 1
  fi

  if [ ${#end_times[@]} -ne 6 ]; then
    echo "ERROR: Expected 6 task end times, got ${#end_times[@]}"
    exit 1
  fi

  # Calculate time differences between task starts (in nanoseconds)
  # For parallel execution, all tasks should start within a small window (< 1 second)
  first_start=${start_times[0]}
  last_start=${start_times[5]}
  start_spread=$((last_start - first_start))

  # Convert nanoseconds to milliseconds for easier interpretation
  start_spread_ms=$((start_spread / 1000000))

  echo "Time between first and last task start: ${start_spread_ms}ms"

  # Check if tasks started in parallel (within 1 second = 1000ms)
  if [ $start_spread_ms -gt 1000 ]; then
    echo "WARNING: Tasks may not be running in parallel. Start spread: ${start_spread_ms}ms"
    echo "This could indicate the original issue is still present."
  else
    echo "✓ Tasks started concurrently (within ${start_spread_ms}ms)"
  fi

  # Critical check: Ensure all tasks start before any task completes
  # This is essential for true parallel execution
  echo "Checking that all tasks start before any complete..."
  last_start_time=${start_times[5]}
  first_end_time=${end_times[0]}

  if [ "$last_start_time" -gt "$first_end_time" ]; then
    echo "ERROR: Some tasks completed before all tasks started!"
    echo "Last task started at: $last_start_time"
    echo "First task completed at: $first_end_time"
    echo "This indicates sequential execution, not parallel execution."
    exit 1
  else
    echo "✓ All tasks started before any completed - confirming parallel execution"
  fi

  # Check total execution time
  # If running sequentially: 6 tasks * 2 seconds = ~12 seconds
  # If running in parallel: ~2-3 seconds (plus overhead)
  if [ $total_time -gt 8 ]; then
    echo "ERROR: Total execution time too long (${total_time}s). Tasks appear to be running sequentially."
    echo "Expected: ~2-4 seconds for parallel execution"
    echo "Got: ${total_time}s (suggests sequential execution)"
    exit 1
  else
    echo "✓ Total execution time acceptable (${total_time}s) - suggests parallel execution"
  fi

  # Verify all tasks completed successfully using the captured output
  for i in {1..6}; do
    if ! grep -q "process${i} complete" <<<"$task_output"; then
      echo "ERROR: process${i} did not complete successfully"
      exit 1
    fi
  done

  echo "✓ All tasks completed successfully in test run $test_run"
done

echo ""
echo "✓ All 3 test runs passed - Parallel task execution test passed"
