#!/usr/bin/env bash
# misc_simulate_json_preflight — `--output json simulate --repl` must emit a
# STRUCTURED error envelope on STDOUT for every pre-flight failure (file-not-
# found, parse error, WFC error, `blocking` feature), instead of the old
# behaviour: plain-text on stderr, EMPTY stdout, exit non-zero. The daemon parses
# stdout, so a bare stderr-exit looked like "nucleos ended unexpectedly".
#
# Contract per failure:
#   * stdout's last line is a one-line JSON envelope with
#       "status":"error","ok":false  and a NON-null "error":"…"
#   * the textual `error:` detail is ALSO kept on stderr (downstream probes,
#     e.g. the `blocking` skip marker, still work)
#   * exit code is preserved (parse/WFC/file-not-found = 1, blocking = 2)
# And, to pin that this is JSON-only: TEXT mode (`simulate --repl`, no
# `--output json`) stays stderr-only with NOTHING on stdout.
set -euo pipefail

# A pre-flight failure aborts before stdin is read, but feed an op anyway so the
# invocation matches the daemon's usage shape.
feed='{"op":"quit"}'

# assert_json_error <label> <expected-exit> <nucleos args...>
assert_json_error() {
  local label="$1"; shift
  local want_rc="$1"; shift
  local out err rc
  out=$(printf '%s\n' "$feed" | "$NUCLEOS" --output json simulate --repl "$@" 2>"$NUCTEST_TMPDIR/err") && rc=0 || rc=$?
  err=$(cat "$NUCTEST_TMPDIR/err")
  local last; last=$(printf '%s\n' "$out" | grep . | tail -1)

  if [[ "$rc" -ne "$want_rc" ]]; then
    echo "FAIL [$label]: exit $rc, expected $want_rc"; echo "stdout: $out"; echo "stderr: $err"; exit 1
  fi
  if [[ -z "$last" ]]; then
    echo "FAIL [$label]: no JSON envelope on stdout (regression: stdout was empty)"; echo "stderr: $err"; exit 1
  fi
  case "$last" in
    *'"status":"error"'*'"ok":false'*) : ;;
    *) echo "FAIL [$label]: stdout envelope missing status/ok=error"; echo "stdout: $last"; exit 1 ;;
  esac
  # error must be a non-null, non-empty string.
  case "$last" in
    *'"error":null'*|*'"error":""'*)
      echo "FAIL [$label]: envelope error is null/empty"; echo "stdout: $last"; exit 1 ;;
  esac
  if [[ -z "$err" ]]; then
    echo "FAIL [$label]: stderr detail missing (downstream probes rely on it)"; exit 1
  fi
  echo "ok [$label]: JSON error envelope on stdout (exit $rc), stderr detail kept"
}

assert_json_error "file-not-found" 1 -m nope "$NUCTEST_TMPDIR/does_not_exist.dzn"
assert_json_error "parse-error"    1 -m parse_error_model "$MODEL_DIR/parse_error.dzn"
assert_json_error "wfc-error"      1 -m wfc_error_model "$MODEL_DIR/wfc_error.dzn"
assert_json_error "blocking"       2 -m blocking_model "$MODEL_DIR/blocking.dzn"

# TEXT mode: no `--output json` → NOTHING on stdout, detail on stderr, exit 2.
out=$(printf 'x\n' | "$NUCLEOS" simulate --repl -m blocking_model "$MODEL_DIR/blocking.dzn" 2>"$NUCTEST_TMPDIR/err") && rc=0 || rc=$?
if [[ -n "$out" ]]; then
  echo "FAIL [blocking-text]: text mode emitted stdout (should be stderr-only)"; echo "stdout: $out"; exit 1
fi
if [[ "$rc" -ne 2 ]]; then
  echo "FAIL [blocking-text]: exit $rc, expected 2"; exit 1
fi
if ! grep -q 'blocking' "$NUCTEST_TMPDIR/err"; then
  echo "FAIL [blocking-text]: stderr missing blocking message"; cat "$NUCTEST_TMPDIR/err"; exit 1
fi
echo "ok [blocking-text]: text mode stays stderr-only (exit 2)"

echo "ok: simulate --output json emits structured pre-flight error envelopes"
