#!/usr/bin/env bash
# Live A/B: the Python Blaze responder vs the Rust sidecar, over real sockets.
#
#   ./check-live-parity.sh <python-host:port> <rust-host:port> [outdir]
#
# Replays the recorded conversations against BOTH endpoints and diffs the
# normalized traces. Session keys and server timestamps are masked, so anything
# that differs is a real behavioural difference.
#
# IMPORTANT: the diff is the test, not the probe's exit code. The probe only
# detects structural anomalies it can see live (missing frames, early close); a
# same-length content change deep inside a notification body shows up ONLY as a
# digest difference in the trace. Verified by mutation.
#
# Read-only against both backends: it opens client connections and sends
# recorded requests. Safe to run while the Python backend is serving.
#
# For the comparison to mean anything, BOTH servers must run the same config —
# same OPENFUT_ADVERTISE, OPENFUT_BIND, POW_CONTENT_HOST and active persona.
# Otherwise legitimate config differences read as parity failures.
set -uo pipefail

PY="${1:-}"
RS="${2:-}"
OUT="${3:-$(mktemp -d)}"

if [[ -z "$PY" || -z "$RS" ]]; then
  echo "usage: $0 <python-host:port> <rust-host:port> [outdir]" >&2
  echo "example: $0 127.0.0.1:42130 127.0.0.1:42230" >&2
  exit 2
fi

cd "$(dirname "$(readlink -f "$0")")/.."
PROBE="./target/debug/blaze-probe"
[[ -x "$PROBE" ]] || PROBE="./target/release/blaze-probe"
if [[ ! -x "$PROBE" ]]; then
  echo "blaze-probe not built; run: cargo build -p openfut-blaze-host" >&2
  exit 2
fi

# This script produces the artefact a migration decision is made from, so it
# refuses to run against a tree that does not correspond to a commit. The
# compiled-in build stamp cannot be trusted for this (cargo will not re-run
# build.rs for another crate's edit), so the check happens here, now.
if git rev-parse --git-dir >/dev/null 2>&1; then
  DIRT="$(git status --porcelain --untracked-files=no -- \
            openfut-blaze-host openfut-adapter-fifa17 openfut-protocol-blaze 2>/dev/null)"
  if [[ -n "$DIRT" && "${ALLOW_DIRTY:-}" != "1" ]]; then
    echo "REFUSING: migration crates have uncommitted changes:" >&2
    echo "$DIRT" | sed 's/^/  /' >&2
    echo >&2
    echo "A parity result from an unidentifiable build is not evidence." >&2
    echo "Commit first, or re-run with ALLOW_DIRTY=1 for a throwaway check." >&2
    exit 2
  fi
fi

mkdir -p "$OUT"
fail=0
frames=0

for sess in main fallbacks locale; do
  "$PROBE" "$PY" --session "$sess" > "$OUT/python-$sess.trace" 2>"$OUT/python-$sess.err" || true
  "$PROBE" "$RS" --session "$sess" > "$OUT/rust-$sess.trace"   2>"$OUT/rust-$sess.err"   || true

  n=$(grep -c '^conn-' "$OUT/python-$sess.trace" || true)
  if diff -u "$OUT/python-$sess.trace" "$OUT/rust-$sess.trace" > "$OUT/diff-$sess.txt"; then
    echo "  $sess: IDENTICAL ($n frames)"
    frames=$((frames + n))
  else
    echo "  $sess: DIFFERS -> $OUT/diff-$sess.txt"
    head -30 "$OUT/diff-$sess.txt"
    fail=1
  fi
done

echo
if [[ $fail -eq 0 ]]; then
  echo "LIVE PARITY OK — $frames frames, identical normalized traces."
  echo "traces: $OUT"
else
  echo "LIVE PARITY FAILED — see $OUT"
fi
exit $fail
