#!/usr/bin/env bash
#
# EL3AB multiplayer + tournament test suite.
#
#   ./tests/run.sh
#
# Everything runs against a throwaway local Postgres carrying a replica of the
# production types and tables. No production data is read or written.
#
# Requires: php (8.1+), node (18+), postgres client tools (initdb, pg_ctl, psql).

set -uo pipefail
cd "$(dirname "$0")"

PGPORT=${PGPORT:-54329}
PGDATA="$PWD/.pgdata"
APIPORT=8788
AUTHPORT=8789
PASS=0
FAIL=0

cleanup() {
  [ -n "${API_PID:-}" ] && kill "$API_PID" 2>/dev/null && wait "$API_PID" 2>/dev/null
  [ -n "${AUTH_PID:-}" ] && kill "$AUTH_PID" 2>/dev/null && wait "$AUTH_PID" 2>/dev/null
  pg_ctl -D "$PGDATA" stop -m immediate >/dev/null 2>&1
  rm -rf "$PGDATA"
}
trap cleanup EXIT

step() { printf '\n\033[1m%s\033[0m\n' "$1"; }
run()  {
  if "${@:2}" > /tmp/el3ab_test_out 2>&1; then
    printf '  \033[32mPASS\033[0m  %s\n' "$1"; PASS=$((PASS+1))
  else
    printf '  \033[31mFAIL\033[0m  %s\n' "$1"; FAIL=$((FAIL+1))
    sed 's/^/        /' /tmp/el3ab_test_out | tail -30
  fi
}

# A server left over from an earlier run would keep serving the OLD code on
# these ports and the suite would silently test the previous revision. Clear
# them first and refuse to continue if they do not free up.
step "Clearing ports $APIPORT and $AUTHPORT"
pkill -f "php .*-S 127.0.0.1:$APIPORT" 2>/dev/null
pkill -f "php .*-S 127.0.0.1:$AUTHPORT" 2>/dev/null
pg_ctl -D "$PGDATA" stop -m immediate >/dev/null 2>&1
for _ in $(seq 1 20); do
  lsof -nP -iTCP:$APIPORT -iTCP:$AUTHPORT -sTCP:LISTEN >/dev/null 2>&1 || break
  sleep 0.5
done
if lsof -nP -iTCP:$APIPORT -iTCP:$AUTHPORT -sTCP:LISTEN >/dev/null 2>&1; then
  echo "  ports still in use — refusing to run against a stale server"
  lsof -nP -iTCP:$APIPORT -iTCP:$AUTHPORT -sTCP:LISTEN
  exit 1
fi
echo "  clear"

step "Starting a disposable Postgres on port $PGPORT"
rm -rf "$PGDATA"
initdb -D "$PGDATA" -U postgres --auth=trust >/dev/null 2>&1
pg_ctl -D "$PGDATA" -o "-p $PGPORT -k /tmp -c listen_addresses='127.0.0.1'" -l "$PWD/.pg.log" start >/dev/null 2>&1
for _ in $(seq 1 20); do
  psql -h 127.0.0.1 -p "$PGPORT" -U postgres -tAc 'select 1' >/dev/null 2>&1 && break
  sleep 0.5
done
psql -h 127.0.0.1 -p "$PGPORT" -U postgres -q -f schema.sql >/dev/null 2>&1
echo "  schema loaded"

step "Starting the API under test"
php -S 127.0.0.1:$AUTHPORT authstub.php > .auth.log 2>&1 &
AUTH_PID=$!
php -d display_errors=Off -S 127.0.0.1:$APIPORT router.php > .server.log 2>&1 &
API_PID=$!
sleep 2
if grep -q "Address already in use" .server.log .auth.log 2>/dev/null; then
  echo "  a server failed to bind — aborting rather than testing stale code"
  cat .server.log .auth.log
  exit 1
fi
echo "  api on :$APIPORT, auth stub on :$AUTHPORT"

step "Tests"
run "Swiss pairing engine + chess result logic (2-100 players)" php test_swiss.php
run "Real master games replayed through the move validator"     php test_replay.php
run "Tournament engine against real Postgres"                   php test_integration.php
run "Local JWT verification (signature, expiry, alg=none)"      php test_auth.php
run "Full API end-to-end: matchmaking, a game, a tournament"    node test_e2e.mjs

printf '\n%d passed, %d failed\n' "$PASS" "$FAIL"
[ "$FAIL" -eq 0 ] || exit 1
