#!/usr/bin/env bash
# dream-on-sx conformance runner — loads all dream modules + test suites in one
# sx_server process and reports pass/fail per suite.
#
# Usage:
#   bash lib/dream/conformance.sh        # run all suites
#   bash lib/dream/conformance.sh -v     # verbose (list each suite)

set -uo pipefail
cd "$(git rev-parse --show-toplevel)"

SX_SERVER="${SX_SERVER:-hosts/ocaml/_build/default/bin/sx_server.exe}"
if [ ! -x "$SX_SERVER" ]; then
  SX_SERVER="/root/rose-ash/hosts/ocaml/_build/default/bin/sx_server.exe"
fi
if [ ! -x "$SX_SERVER" ]; then
  echo "ERROR: sx_server.exe not found." >&2
  exit 1
fi

VERBOSE="${1:-}"

# Dream library modules loaded before any test suite.
MODULES=(
  "lib/dream/types.sx"
  "lib/dream/router.sx"
  "lib/dream/middleware.sx"
  "lib/dream/session.sx"
  "lib/dream/flash.sx"
  "lib/dream/form.sx"
  "lib/dream/websocket.sx"
  "lib/dream/static.sx"
  "lib/dream/error.sx"
  "lib/dream/cors.sx"
  "lib/dream/json.sx"
  "lib/dream/auth.sx"
  "lib/dream/html.sx"
  "lib/dream/headers.sx"
  "lib/dream/run.sx"
  "lib/dream/api.sx"
  "lib/dream/demos/hello.sx"
  "lib/dream/demos/counter.sx"
  "lib/dream/demos/chat.sx"
  "lib/dream/demos/todo.sx"
)

# Suites: NAME RUNNER-FN PATH
SUITES=(
  "types       dream-ty-tests-run!  lib/dream/tests/types.sx"
  "router      dream-rt-tests-run!  lib/dream/tests/router.sx"
  "middleware  dream-mw-tests-run!  lib/dream/tests/middleware.sx"
  "session     dream-ss-tests-run!  lib/dream/tests/session.sx"
  "flash       dream-fl-tests-run!  lib/dream/tests/flash.sx"
  "form        dream-fo-tests-run!  lib/dream/tests/form.sx"
  "websocket   dream-ws-tests-run!  lib/dream/tests/websocket.sx"
  "static      dream-st-tests-run!  lib/dream/tests/static.sx"
  "error       dream-er-tests-run!  lib/dream/tests/error.sx"
  "cors        dream-co-tests-run!  lib/dream/tests/cors.sx"
  "json        dream-js-tests-run!  lib/dream/tests/json.sx"
  "auth        dream-au-tests-run!  lib/dream/tests/auth.sx"
  "html        dream-ht-tests-run!  lib/dream/tests/html.sx"
  "headers     dream-hd-tests-run!  lib/dream/tests/headers.sx"
  "run         dream-rn-tests-run!  lib/dream/tests/run.sx"
  "api         dream-ap-tests-run!  lib/dream/tests/api.sx"
  "demos       dream-dm-tests-run!  lib/dream/tests/demos.sx"
)

TMPFILE=$(mktemp); trap "rm -f $TMPFILE" EXIT
EPOCH=1
emit_load () { echo "(epoch $EPOCH)"; echo "(load \"$1\")"; EPOCH=$((EPOCH+1)); }
emit_eval () { echo "(epoch $EPOCH)"; echo "(eval \"$1\")"; EPOCH=$((EPOCH+1)); }

{
  for M in "${MODULES[@]}"; do emit_load "$M"; done
  for SUITE in "${SUITES[@]}"; do
    read -r _NAME _RUNNER FILE <<< "$SUITE"
    emit_load "$FILE"
    emit_eval "($_RUNNER)"
  done
} > "$TMPFILE"

OUTPUT=$(timeout 540 "$SX_SERVER" < "$TMPFILE" 2>&1 || true)

TOTAL_PASS=0
TOTAL_FAIL=0
FAILED_SUITES=()
LAST_DICT_LINES=$(echo "$OUTPUT" | grep -E '^\{:' || true)

I=0
while read -r LINE; do
  [ -z "$LINE" ] && continue
  P=$(echo "$LINE" | grep -oE ':passed [0-9]+' | awk '{print $2}')
  F=$(echo "$LINE" | grep -oE ':failed [0-9]+' | awk '{print $2}')
  [ -z "$P" ] && P=0
  [ -z "$F" ] && F=0
  SUITE_INFO="${SUITES[$I]}"
  SUITE_NAME=$(echo "$SUITE_INFO" | awk '{print $1}')
  TOTAL_PASS=$((TOTAL_PASS + P))
  TOTAL_FAIL=$((TOTAL_FAIL + F))
  if [ "$F" -gt 0 ]; then
    FAILED_SUITES+=("$SUITE_NAME: $P/$((P+F))")
    printf 'X %-12s %d/%d\n' "$SUITE_NAME" "$P" "$((P+F))"
    echo "$LINE" | grep -oE ':name "[^"]*"' | sed 's/:name /    fail: /'
  elif [ "$VERBOSE" = "-v" ]; then
    printf 'ok %-12s %d passed\n' "$SUITE_NAME" "$P"
  fi
  I=$((I+1))
done <<< "$LAST_DICT_LINES"

TOTAL=$((TOTAL_PASS + TOTAL_FAIL))
if [ "$TOTAL" -eq 0 ]; then
  echo "ERROR: no suite results parsed. Raw output:" >&2
  echo "$OUTPUT" >&2
  exit 1
fi
if [ $TOTAL_FAIL -eq 0 ]; then
  echo "ok $TOTAL_PASS/$TOTAL dream-on-sx tests passed (${#SUITES[@]} suites)"
else
  echo "FAIL $TOTAL_PASS/$TOTAL passed, $TOTAL_FAIL failed:"
  for S in "${FAILED_SUITES[@]}"; do echo "  $S"; done
  exit 1
fi
