#!/usr/bin/env bash

set -euo pipefail

# Ambient agent RUNPLAN_ALLOW_ONLINE must not widen offline provision test defaults.
unset RUNPLAN_ALLOW_ONLINE
unset HARNESS_ENGINE_DEV

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

TEST_FILE_TIMEOUT="${TEST_FILE_TIMEOUT:-600}"
NODE_TEST_TIMEOUT_MS="${NODE_TEST_TIMEOUT_MS:-60000}"

run_bounded() {
  local rel_path="$1"
  shift
  local rc=0
  timeout --kill-after=10s "$TEST_FILE_TIMEOUT" "$@" || rc=$?
  if [[ "$rc" -eq 124 || "$rc" -eq 137 ]]; then
    printf 'TIMEOUT %s exceeded %ss (fail-closed)\n' "$rel_path" "$TEST_FILE_TIMEOUT" >&2
    return 1
  fi
  return "$rc"
}

discover_tests() {
  local -a patterns=(
    "test/*.sh"
    "test/**/*.sh"
    "**/*.test.sh"
    "**/test-*.sh"
    "**/*.test.js"
    "**/test-*.js"
  )
  local pattern

  (
    cd "$ROOT_DIR"
    shopt -s globstar nullglob

    for pattern in "${patterns[@]}"; do
      local -a matches=($pattern)
      local path
      for path in "${matches[@]}"; do
        [[ -f "$path" ]] || continue
        [[ "$path" == "run-tests.sh" ]] && continue
        [[ "$path" == "test/run-tests-entrypoint.sh" ]] && continue
        [[ "$path" == *node_modules* ]] && continue
        [[ "$path" == tmp/* ]] && continue
        [[ "$path" == runstate/* ]] && continue
        [[ "$path" == .runplan-cache/* ]] && continue
        printf '%s\n' "$path"
      done
    done
  ) | LC_ALL=C sort -u
}

run_test_file() {
  local rel_path="$1"

  case "$rel_path" in
    *.sh)
      printf 'RUN %s\n' "$rel_path"
      (cd "$ROOT_DIR" && run_bounded "$rel_path" bash "$rel_path")
      ;;
    *.js)
      printf 'RUN %s\n' "$rel_path"
      (cd "$ROOT_DIR" && run_bounded "$rel_path" node --test "--test-concurrency=1" "--test-timeout=$NODE_TEST_TIMEOUT_MS" "$rel_path")
      ;;
    *)
      printf 'Unsupported test file: %s\n' "$rel_path" >&2
      return 1
      ;;
  esac
}

print_dry_run() {
  local test_file
  for test_file in "$@"; do
    case "$test_file" in
      *.sh)
        printf 'bash "%s/%s"\n' "$ROOT_DIR" "$test_file"
        ;;
      *.js)
        printf 'node "%s/%s"\n' "$ROOT_DIR" "$test_file"
        ;;
      *)
        printf 'Unsupported test file: %s\n' "$test_file" >&2
        return 1
        ;;
    esac
  done
}

assert_contains() {
  local haystack="$1"
  local needle="$2"

  if [[ "$haystack" != *"$needle"* ]]; then
    printf 'Expected output to contain: %s\n' "$needle" >&2
    return 1
  fi
}

run_self_test_case() {
  local name="$1"
  local setup_script="$2"
  local expected_rc="$3"
  shift 3

  local tmpdir=""
  tmpdir="$(mktemp -d)"
  trap '[[ -n "${tmpdir:-}" ]] && rm -rf "$tmpdir"' RETURN

  cp "$ROOT_DIR/run-tests.sh" "$tmpdir/run-tests.sh"
  chmod +x "$tmpdir/run-tests.sh"
  (
    cd "$tmpdir"
    eval "$setup_script"
  )

  local output rc
  output="$(
    cd "$tmpdir"
    bash ./run-tests.sh 2>&1
  )" || rc=$?
  rc="${rc:-0}"

  if [[ "$rc" -ne "$expected_rc" ]]; then
    printf 'Self-test failed: %s\n' "$name" >&2
    printf 'Expected exit code %s, got %s\n' "$expected_rc" "$rc" >&2
    printf '%s\n' "$output" >&2
    return 1
  fi

  local expectation
  for expectation in "$@"; do
    assert_contains "$output" "$expectation"
  done

  printf 'PASS %s\n' "$name"
}

run_self_tests() {
  run_self_test_case \
    "zero-tests-fails-closed" \
    ":" \
    1 \
    "No tests found."

  run_self_test_case \
    "mixed-test-discovery" \
    "mkdir -p test/chaos pkg nested && \
      printf '#!/usr/bin/env bash\nprintf shell-a\\\\n' > test/a.sh && \
      printf '#!/usr/bin/env bash\nprintf shell-chaos\\\\n' > test/chaos/babysit.sh && \
      printf '#!/usr/bin/env bash\nprintf shell-b\\\\n' > pkg/example.test.sh && \
      printf 'console.log(\"node-a\")\n' > nested/test-sample.js" \
    0 \
    "RUN nested/test-sample.js" \
    "RUN pkg/example.test.sh" \
    "RUN test/a.sh" \
    "RUN test/chaos/babysit.sh" \
    "node-a" \
    "shell-a" \
    "shell-chaos" \
    "shell-b"

  run_self_test_case \
    "failure-propagates" \
    "mkdir -p test pkg && \
      printf '#!/usr/bin/env bash\nprintf first\\\\n' > test/a.sh && \
      printf '#!/usr/bin/env bash\nexit 7\n' > pkg/test-fail.sh" \
    7 \
    "RUN pkg/test-fail.sh"
}

main() {
  if [[ "${1:-}" == "--self-test" ]]; then
    run_self_tests
    return 0
  fi

  mapfile -t tests < <(discover_tests)

  if [[ "${#tests[@]}" -eq 0 ]]; then
    printf 'No tests found.\n' >&2
    return 1
  fi

  if [[ "${1:-}" == "--dry-run" ]]; then
    print_dry_run "${tests[@]}"
    return 0
  fi

  local test_file
  for test_file in "${tests[@]}"; do
    run_test_file "$test_file"
  done
}

main "$@"
