#!/usr/bin/env bash
# El pre-commit hook: compile and run native tests before commit.
# Install once per clone: git config core.hooksPath .githooks

set -euo pipefail

ROOT="$(git rev-parse --show-toplevel)"
LANG_DIR="$ROOT/lang"
RUNTIME="$LANG_DIR/runtime"
ELC="$LANG_DIR/dist/platform/elc"

# If elc isn't built yet, skip with a warning rather than blocking
if [ ! -x "$ELC" ]; then
  echo "⚠  elc not found at lang/dist/platform/elc — skipping pre-commit tests"
  echo "   Build it first: see 'Rebuilding the Compiler' in lang/AGENTS.md"
  echo "   (link \$($ROOT/scripts/el-runtime-sources.sh $RUNTIME) — NOT el_runtime.c alone)"
  exit 0
fi

# The runtime is MULTI-FILE (lang/runtime/SOURCES). This hook used to link
# "$RUNTIME/el_runtime.c" alone with stderr sent to /dev/null — so once
# el_runtime.c started calling into the engram siblings, every native test
# reported as FAILED with the real `ld` error invisible. Build the whole set
# once into an archive, then link each test against it.

# macOS: Homebrew openssl@3 is not on the default include/lib search path, so
# without these the link fails on -lssl/-lcrypto. Empty on Linux/CI.
SSL_INC=""
SSL_LIB=""
if command -v brew >/dev/null 2>&1 && OSSL="$(brew --prefix openssl@3 2>/dev/null)" && [ -n "$OSSL" ]; then
  SSL_INC="-I$OSSL/include"
  SSL_LIB="-L$OSSL/lib"
fi

echo "→ Building runtime (compile-once, link-many)..."
HOOK_LIB="/tmp/el_hook_libel.a"
HOOK_OBJ="/tmp/el_hook_obj"
rm -rf "$HOOK_OBJ" && mkdir -p "$HOOK_OBJ"
if ! for src in $("$ROOT/scripts/el-runtime-sources.sh" --check "$RUNTIME"); do
       gcc -O2 -c -I "$RUNTIME" $SSL_INC "$src" -o "$HOOK_OBJ/$(basename "${src%.c}").o" || exit 1
     done; then
  echo "✗ Pre-commit failed: the runtime does not compile."
  echo "  Re-run without 2>/dev/null to see the error:"
  echo "    gcc -O2 -c -I $RUNTIME \$($ROOT/scripts/el-runtime-sources.sh $RUNTIME)"
  exit 1
fi
ar rcs "$HOOK_LIB" "$HOOK_OBJ"/*.o

echo "→ Running El native tests..."
PASS=0
FAIL=0
FAILED_TESTS=""

for test_file in "$LANG_DIR"/tests/native/test_*.el; do
  name=$(basename "$test_file" .el)
  tmp_c="/tmp/el_hook_${name}.c"
  tmp_bin="/tmp/el_hook_${name}"

  if "$ELC" --test "$test_file" > "$tmp_c" 2>/dev/null \
     && gcc -O2 -I "$RUNTIME" $SSL_INC $SSL_LIB "$tmp_c" "$HOOK_LIB" \
          -lcurl -lssl -lcrypto -lpthread -lm -o "$tmp_bin" 2>/dev/null \
     && "$tmp_bin" 2>/dev/null; then
    PASS=$((PASS + 1))
  else
    echo "  ✗ $name"
    FAIL=$((FAIL + 1))
    FAILED_TESTS="$FAILED_TESTS $name"
  fi
done

echo "  $PASS passed, $FAIL failed"

if [ "$FAIL" -gt 0 ]; then
  echo ""
  echo "✗ Pre-commit failed. Fix these tests before committing:$FAILED_TESTS"
  exit 1
fi

echo "✓ All tests passed"
exit 0
