#!/usr/bin/env bash
# Real-Server check that two concurrent org-key bootstraps converge on ONE key
# (et-ai-labs/Thalamus#1956): the CLI's getOrgKey and the App's fetchAndUnwrapOrgKey, acting as the
# same owner account (CLI + App open together), start on a shared barrier against Server's ISOLATED
# dev loop. Each round the org's wraps are reset to null, both race, then the owner and every other
# member resolve their own wrap; all fingerprints (racers and members) must be identical.
#
# Brings up its OWN compose project and Server, and tears both down (down -v) on exit. Never touches
# prod; every server URL is loopback. Nothing here prints a key, only a 16-hex SHA-256 fingerprint.
#
#   SERVER_DIR=<Server checkout> APP_DIR=<App checkout> OUT=<scratch dir outside every repo> \
#     [ROUNDS=5] [PROJECT=thalamus-server-dev-orgkeyrace] scripts/orgkey-race-check.sh
set -euo pipefail

: "${SERVER_DIR:?set SERVER_DIR to the Server checkout}"
: "${APP_DIR:?set APP_DIR to the App checkout}"
: "${OUT:?set OUT to a scratch directory outside every repo}"
ROUNDS="${ROUNDS:-5}"
export COMPOSE_PROJECT_NAME="${PROJECT:-thalamus-server-dev-orgkeyrace}"
export POSTGRES_PORT="${POSTGRES_PORT:-5553}" REDIS_PORT="${REDIS_PORT:-6553}" MINIO_PORT="${MINIO_PORT:-9052}" MINIO_CONSOLE_PORT="${MINIO_CONSOLE_PORT:-9053}"
PORT="${PORT:-3057}"
export DATABASE_URL="postgresql://postgres:postgres@localhost:${POSTGRES_PORT}/thalamus"
export REDIS_URL="redis://localhost:${REDIS_PORT}"
export S3_PORT="$MINIO_PORT" S3_PUBLIC_URL="http://localhost:${MINIO_PORT}/thalamus"
export PORT METRICS_ENABLED=false
export THALAMUS_SERVER_URL="http://localhost:${PORT}"

CLI_DIR="$(cd "$(dirname "$0")/.." && pwd)"
mkdir -p "$OUT"; chmod 700 "$OUT"
SERVER_PID=""

cleanup() {
    [ -n "$SERVER_PID" ] && kill "$SERVER_PID" 2>/dev/null || true
    (cd "$SERVER_DIR" && docker compose --env-file .env.dev down -v) >/dev/null 2>&1 || true
}
trap cleanup EXIT

fixture() { (cd "$CLI_DIR" && node_modules/.bin/tsx scripts/live-org-fixture.ts "$@"); }
racecli() { (cd "$CLI_DIR" && node_modules/.bin/tsx scripts/orgkey-race-check.ts "$@"); }
rand() { head -c 18 /dev/urandom | base64 | tr -d '/+=\n'; }

(cd "$SERVER_DIR" && docker compose --env-file .env.dev up -d postgres redis minio)
for _ in $(seq 1 60); do
    docker exec "${COMPOSE_PROJECT_NAME}-postgres-1" pg_isready -U postgres >/dev/null 2>&1 && break
    sleep 1
done
(cd "$SERVER_DIR" && yarn prisma migrate deploy >"$OUT/migrate.log" 2>&1)
(cd "$SERVER_DIR" && yarn tsx --env-file=.env.dev sources/main.ts >"$OUT/server.log" 2>&1) &
SERVER_PID=$!
for _ in $(seq 1 60); do
    curl -fs "$THALAMUS_SERVER_URL/health" >/dev/null 2>&1 && break
    kill -0 "$SERVER_PID" 2>/dev/null || { echo "server exited; see $OUT/server.log" >&2; exit 1; }
    sleep 1
done

SUFFIX="$(head -c 4 /dev/urandom | od -An -tx1 | tr -d ' \n')"
EMAILS=("owner-$SUFFIX@fixture.invalid" "m1-$SUFFIX@fixture.invalid" "m2-$SUFFIX@fixture.invalid")
HOMES=("$OUT/owner" "$OUT/m1" "$OUT/m2")
for i in 0 1 2; do THALAMUS_HOME_DIR="${HOMES[$i]}" fixture register "${EMAILS[$i]}" "$(rand)" >/dev/null; done
(cd "$SERVER_DIR" && FOUNDER_EMAILS="$(IFS=,; echo "${EMAILS[*]}")" yarn tsx sources/scripts/provisionOrgs.ts >/dev/null)
ORG_ID="$(THALAMUS_HOME_DIR="${HOMES[0]}" fixture org-id)"
echo "org $ORG_ID, $ROUNDS round(s)"

reset_wraps() {
    docker exec "${COMPOSE_PROJECT_NAME}-postgres-1" psql -U postgres -d thalamus -qtAc \
        "UPDATE \"Membership\" SET \"orgKeyWrap\" = NULL WHERE \"orgId\" = '$ORG_ID'" >/dev/null
}

fail=0
LOSERS=0
for round in $(seq 1 "$ROUNDS"); do
    reset_wraps
    GO_AT=$(node -e "console.log(Date.now() + 6000)")   # start barrier: both racers load, then fire together
    THALAMUS_HOME_DIR="${HOMES[0]}" racecli race "$ORG_ID" "$GO_AT" "$OUT/cli.fp" >"$OUT/cli.out" 2>&1 &
    CLI_PID=$!
    (cd "$APP_DIR" && ORGKEY_RACE_SERVER="$THALAMUS_SERVER_URL" ORGKEY_RACE_KEYFILE="${HOMES[0]}/access.key" \
        ORGKEY_RACE_ORG="$ORG_ID" ORGKEY_RACE_GO_AT="$GO_AT" ORGKEY_RACE_OUT="$OUT/app.fp" \
        yarn vitest run sources/sync/apiOrgKey.race.spec.ts >"$OUT/app.out" 2>&1) &
    APP_PID=$!
    wait "$CLI_PID" || { echo "round $round: CLI racer failed"; cat "$OUT/cli.out"; fail=1; }
    wait "$APP_PID" || { echo "round $round: App racer failed"; tail -30 "$OUT/app.out"; fail=1; }

    FPS=("$(head -1 "$OUT/cli.fp")" "$(head -1 "$OUT/app.fp")")
    STATUSES="cli=$(sed -n 2p "$OUT/cli.fp") app=$(sed -n 2p "$OUT/app.fp")"
    for i in 0 1 2; do
        THALAMUS_HOME_DIR="${HOMES[$i]}" racecli resolve "$ORG_ID" "$OUT/m$i.fp" >/dev/null
        FPS+=("$(head -1 "$OUT/m$i.fp")")
    done
    UNIQUE="$(printf '%s\n' "${FPS[@]}" | sort -u | wc -l)"
    echo "round $round: cli=${FPS[0]} app=${FPS[1]} owner=${FPS[2]} m1=${FPS[3]} m2=${FPS[4]} distinct=$UNIQUE batchPUT[$STATUSES]"
    if [ "$UNIQUE" != 1 ] || [ "${FPS[0]}" = "NULL" ]; then fail=1; fi
    # At most one racer may have WON the batch PUT; the other either lost (409) or arrived after.
    if [ "$(sed -n 2p "$OUT/cli.fp")$(sed -n 2p "$OUT/app.fp")" = "200200" ]; then echo "round $round: both batch PUTs returned 200" >&2; fail=1; fi
    LOSERS=$(( LOSERS + $(cat "$OUT/cli.fp" "$OUT/app.fp" | grep -c '^409$' || true) ))
done

echo "409 losers observed across rounds: $LOSERS"
[ "$fail" = 0 ] && echo "PASS: every round ended with every member holding the same key" || { echo "FAIL" >&2; exit 1; }
