#!/usr/bin/env bash
# validator_parity — send identical /v1/validate requests to BOTH the
# Rust gateway (default :3100) and the Go gateway (default :4110),
# compare HTTP status + body. Mismatches surface in the OUTPUT report
# as a [DIFF] row; converging behavior is captured as [MATCH].
#
# This exploits the dual-implementation as a measurement instrument:
# a divergence is a finding the architecture comparison should record.
#
# Usage:
#   ./scripts/cutover/parity/validator_parity.sh
#
# Env overrides:
#   RUST_GW=http://127.0.0.1:3100   # Rust gateway URL
#   GO_GW=http://127.0.0.1:4110     # Go gateway URL (persistent stack)

set -euo pipefail
cd "$(dirname "$0")/../../.."

RUST_GW="${RUST_GW:-http://127.0.0.1:3100}"
GO_GW="${GO_GW:-http://127.0.0.1:4110}"
OUT_DIR="reports/cutover/gauntlet_2026-05-02/parity"
mkdir -p "$OUT_DIR"
OUT="$OUT_DIR/validator_parity.md"

# Test cases: pairs of (label, kind, body). Selected to cover every
# branch of the validator code paths AND failure modes that should
# hit the same status code on both runtimes.
declare -a CASES=(
  "playbook_happy|playbook|{\"operation\":\"fill: Welder x2 in Toledo, OH\",\"endorsed_names\":[\"W-1\",\"W-2\"],\"target_count\":2,\"fingerprint\":\"abc123\"}"
  "playbook_missing_fingerprint|playbook|{\"operation\":\"fill: X x1 in A, B\",\"endorsed_names\":[\"a\"]}"
  "playbook_wrong_prefix|playbook|{\"operation\":\"sms_draft: hello\",\"endorsed_names\":[\"a\"],\"fingerprint\":\"x\"}"
  "playbook_empty_endorsed|playbook|{\"operation\":\"fill: X x1 in A, B\",\"endorsed_names\":[],\"fingerprint\":\"x\"}"
  "playbook_overfull|playbook|{\"operation\":\"fill: X x1 in A, B\",\"endorsed_names\":[\"a\",\"b\",\"c\"],\"target_count\":1,\"fingerprint\":\"x\"}"
  "fill_phantom|fill|{\"fills\":[{\"candidate_id\":\"W-PHANTOM-NEVER-EXISTS\",\"name\":\"Nobody\"}]}|{\"target_count\":1,\"city\":\"Toledo\",\"client_id\":\"C-1\"}"
)

probe() {
  local gw="$1" kind="$2" artifact="$3" ctx="$4"
  local body
  if [ -n "$ctx" ]; then
    body=$(jq -nc --argjson art "$artifact" --argjson c "$ctx" --arg k "$kind" '{kind:$k, artifact:$art, context:$c}')
  else
    body=$(jq -nc --argjson art "$artifact" --arg k "$kind" '{kind:$k, artifact:$art}')
  fi
  curl -sS -m 8 -o /tmp/parity_resp.json -w "%{http_code}" \
    -X POST "$gw/v1/validate" \
    -H 'Content-Type: application/json' \
    --data-binary "$body"
  echo
}

normalize() {
  # Strip elapsed_ms (timing) so the body comparison is content-only.
  jq -S 'del(.elapsed_ms)' "$1" 2>/dev/null || cat "$1"
}

{
  echo "# Validator parity probe — Rust :3100 vs Go :4110"
  echo
  echo "**Date:** $(date -u +%Y-%m-%dT%H:%M:%SZ)"
  echo "**Rust gateway:** \`$RUST_GW\`  ·  **Go gateway:** \`$GO_GW\`"
  echo
  echo "Identical \`POST /v1/validate\` request → both runtimes. Match"
  echo "= identical HTTP status + identical body (modulo \`elapsed_ms\`)."
  echo
  echo "| Case | Rust status | Go status | Status match | Body match |"
  echo "|---|---:|---:|:---:|:---:|"
} > "$OUT"

MATCH=0; DIFF=0
for entry in "${CASES[@]}"; do
  IFS='|' read -r label kind artifact ctx <<<"$entry"
  rust_status=$(probe "$RUST_GW" "$kind" "$artifact" "$ctx" || echo "000")
  cp /tmp/parity_resp.json /tmp/parity_rust.json
  go_status=$(probe "$GO_GW" "$kind" "$artifact" "$ctx" || echo "000")
  cp /tmp/parity_resp.json /tmp/parity_go.json

  rust_norm=$(normalize /tmp/parity_rust.json)
  go_norm=$(normalize /tmp/parity_go.json)

  status_match="✓"
  body_match="✓"
  if [ "$rust_status" != "$go_status" ]; then status_match="✗"; fi
  if [ "$rust_norm"   != "$go_norm"   ]; then body_match="✗"; fi
  if [ "$status_match" = "✓" ] && [ "$body_match" = "✓" ]; then
    MATCH=$((MATCH+1))
  else
    DIFF=$((DIFF+1))
    # Capture the divergence verbatim for the report.
    {
      echo
      echo "<details><summary>DIFF — \`$label\`</summary>"
      echo
      echo "**Rust** (HTTP $rust_status):"
      echo '```json'
      echo "$rust_norm"
      echo '```'
      echo
      echo "**Go** (HTTP $go_status):"
      echo '```json'
      echo "$go_norm"
      echo '```'
      echo
      echo "</details>"
    } >> "$OUT.diffs"
  fi
  echo "| $label | $rust_status | $go_status | $status_match | $body_match |" >> "$OUT"
done

{
  echo
  echo "**Tally:** $MATCH match · $DIFF diff (out of $((MATCH+DIFF)) cases)"
  echo
  if [ -f "$OUT.diffs" ]; then
    echo "## Divergences"
    cat "$OUT.diffs"
    rm -f "$OUT.diffs"
  fi
} >> "$OUT"

echo "[parity] validator: $MATCH match / $DIFF diff (out of $((MATCH+DIFF))) → $OUT"
[ "$DIFF" -eq 0 ]
