#!/bin/bash
# Run the Mnemosyne Django test suite against an ephemeral Postgres + Neo4j.
#
# Pattern borrowed from spelunker/test-postgres.sh. Both databases run as
# throwaway Docker containers on a private bridge network; each invocation
# gets a fresh pair. The Django test runner applies migrations to the
# empty Postgres and tears the whole network down on exit.
#
# Neo4j is included because a handful of library/tests/* modules touch
# neomodel at import time even though the assertions themselves stub the
# cypher layer; having a reachable bolt endpoint keeps startup probes
# from crashing.
#
# Usage:
#   ./test-postgres.sh                     # run everything
#   ./test-postgres.sh mcp_server          # scope to one app
#   ./test-postgres.sh mcp_server.tests.test_auth
#   ./test-postgres.sh mcp_server -v 2 --failfast

set -euo pipefail

# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------

NET="mnemosyne-test-$$"
PG_CONTAINER="mnemosyne-test-pg-$$"
NEO_CONTAINER="mnemosyne-test-neo4j-$$"
PG_USER="mnemosyne"
PG_PASS="mnemosyne"
PG_DB="mnemosyne_test"
NEO_PASS="mnemosynetestpw"  # Neo4j rejects short or obvious secrets.

IMAGE="git.helu.ca/r/mnemosyne:latest"

# Colours (skipped when not a TTY).
if [ -t 1 ]; then
  GREEN='\033[0;32m'; RED='\033[0;31m'; YELLOW='\033[1;33m'; NC='\033[0m'
else
  GREEN=''; RED=''; YELLOW=''; NC=''
fi

say()   { printf "${GREEN}==> %s${NC}\n" "$*"; }
warn()  { printf "${YELLOW}[!]  %s${NC}\n" "$*"; }
die()   { printf "${RED}[✗]  %s${NC}\n" "$*" >&2; exit 1; }

# ---------------------------------------------------------------------------
# Cleanup
# ---------------------------------------------------------------------------

cleanup() {
  say "Cleaning up test containers"
  docker rm -f "$PG_CONTAINER" >/dev/null 2>&1 || true
  docker rm -f "$NEO_CONTAINER" >/dev/null 2>&1 || true
  docker network rm "$NET" >/dev/null 2>&1 || true
}
trap cleanup EXIT

# ---------------------------------------------------------------------------
# Start the support services
# ---------------------------------------------------------------------------

say "Creating Docker network $NET"
docker network create "$NET" >/dev/null

say "Starting Postgres ($PG_CONTAINER)"
docker run -d --rm \
  --name "$PG_CONTAINER" \
  --network "$NET" \
  -e POSTGRES_USER="$PG_USER" \
  -e POSTGRES_PASSWORD="$PG_PASS" \
  -e POSTGRES_DB="$PG_DB" \
  postgres:16-alpine \
  >/dev/null

say "Starting Neo4j ($NEO_CONTAINER)"
docker run -d --rm \
  --name "$NEO_CONTAINER" \
  --network "$NET" \
  -e NEO4J_AUTH="neo4j/$NEO_PASS" \
  -e NEO4J_PLUGINS='["apoc"]' \
  neo4j:5-community \
  >/dev/null

# Wait for Postgres to accept connections.
say "Waiting for Postgres to become ready"
for i in $(seq 1 30); do
  if docker exec "$PG_CONTAINER" pg_isready -U "$PG_USER" -d "$PG_DB" >/dev/null 2>&1; then
    break
  fi
  sleep 1
done
docker exec "$PG_CONTAINER" pg_isready -U "$PG_USER" -d "$PG_DB" >/dev/null \
  || die "Postgres never became ready"

# Wait for Neo4j's HTTP endpoint — bolt comes up just after it.
say "Waiting for Neo4j to become ready"
for i in $(seq 1 60); do
  if docker exec "$NEO_CONTAINER" wget -qO- http://localhost:7474/ >/dev/null 2>&1; then
    break
  fi
  sleep 1
done

# ---------------------------------------------------------------------------
# Run the test command
# ---------------------------------------------------------------------------

SOURCE_DIR="$(cd "$(dirname "$0")" && pwd)/mnemosyne"

say "Running Django test suite"
docker run --rm \
  --network "$NET" \
  -v "$SOURCE_DIR":/app \
  -w /app \
  -e DJANGO_SETTINGS_MODULE=mnemosyne.settings \
  -e APP_DB_NAME="$PG_DB" \
  -e APP_DB_USER="$PG_USER" \
  -e APP_DB_PASSWORD="$PG_PASS" \
  -e DB_HOST="$PG_CONTAINER" \
  -e DB_PORT=5432 \
  -e NEOMODEL_NEO4J_BOLT_URL="bolt://neo4j:$NEO_PASS@$NEO_CONTAINER:7687" \
  -e SECRET_KEY=test-only-not-a-real-secret \
  -e DEBUG=0 \
  -e MCP_REQUIRE_AUTH=True \
  "$IMAGE" \
  python manage.py test "$@"
