#!/usr/bin/env bash
# run_stress.sh — Capacity/stress harness for the streaming chain.
#
#   MARTe2 app (FileReader -> IOGAM -> UDPStreamer)
#     -> UDPS -> StreamHub(s) -> chain-client(s) (stress: liveness + zoom latency)
#       -> proc_perf (cpu/peakRSS) -> per-case gate -> stress_results.json
#
# It sweeps one load axis at a time (signal size/count, subscriber fan-out, source
# count, WS-client count, zoom request rate — see stress.py) and gates each case on
# survival + liveness (hard) and RSS + zoom-p95 latency (soft). This is the
# capacity sibling of run_e2e.sh (which gates waveform correctness).
#
# Usage: ./run_stress.sh [--skip-build] [--only <id>] [--axis <axis>]
set -u

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
TARGET=x86-linux
BUILD_DIR="${REPO_ROOT}/Build/${TARGET}"
OUT_DIR="${BUILD_DIR}/E2E/chain/stress"
WORK="/tmp/chain_stress"
mkdir -p "${OUT_DIR}" "${WORK}"

SKIP_BUILD=0
ONLY=""
AXIS=""
while [ $# -gt 0 ]; do
    case "$1" in
        --skip-build) SKIP_BUILD=1 ;;
        --only) shift; ONLY="$1" ;;
        --axis) shift; AXIS="$1" ;;
        --help|-h) echo "Usage: $0 [--skip-build] [--only <id>] [--axis <axis>]"; exit 0 ;;
        *) echo "unknown arg $1" >&2; exit 2 ;;
    esac
    shift
done

ENV_SCRIPT="${REPO_ROOT}/env.sh"
[ -f "${ENV_SCRIPT}" ] || { echo "ERROR: ${ENV_SCRIPT} not found" >&2; exit 1; }
: "${LD_LIBRARY_PATH:=}"
source "${ENV_SCRIPT}"

COMP="${MARTe2_Components_DIR}/Build/${TARGET}/Components"
export LD_LIBRARY_PATH="\
${BUILD_DIR}/Components/DataSources/UDPStreamer:\
${BUILD_DIR}/Components/Interfaces/UDPStream:\
${MARTe2_DIR}/Build/${TARGET}/Core:\
${COMP}/DataSources/LinuxTimer:\
${COMP}/DataSources/FileDataSource:\
${COMP}/GAMs/IOGAM:\
${LD_LIBRARY_PATH:-}"

MARTE_APP="${MARTe2_DIR}/Build/${TARGET}/App/MARTeApp.ex"
STREAMHUB_EX="${BUILD_DIR}/StreamHub/StreamHub.ex"
CLIENT="${SCRIPT_DIR}/client/chain-client"
PY="python3"

# ── Build ────────────────────────────────────────────────────────────────────
if [ "${SKIP_BUILD}" -eq 0 ]; then
    echo "── Building components ──"
    make -C "${REPO_ROOT}/Source/Components/Interfaces/UDPStream" -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -1
    make -C "${REPO_ROOT}/Source/Components/DataSources/UDPStreamer" -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -1
    make -C "${REPO_ROOT}/Source/Applications/StreamHub" -f Makefile.gcc TARGET="${TARGET}" 2>&1 | tail -1
fi
if [ ! -x "${CLIENT}" ] || [ "${SKIP_BUILD}" -eq 0 ]; then
    echo "── Building chain-client ──"
    (cd "${SCRIPT_DIR}/client" && go build -o chain-client .) || { echo "client build failed"; exit 1; }
fi
[ -x "${MARTE_APP}" ] || { echo "ERROR: MARTeApp.ex not found at ${MARTE_APP}" >&2; exit 1; }
[ -x "${STREAMHUB_EX}" ] || { echo "ERROR: StreamHub.ex not found" >&2; exit 1; }

# ── Validate the matrix, then run ────────────────────────────────────────────
${PY} "${SCRIPT_DIR}/stress.py" >/dev/null || { echo "stress matrix invalid"; exit 1; }

ARGS=(--marte "${MARTE_APP}" --hub "${STREAMHUB_EX}" --client "${CLIENT}"
      --work "${WORK}" --out "${OUT_DIR}")
[ -n "${ONLY}" ] && ARGS+=(--only "${ONLY}")
[ -n "${AXIS}" ] && ARGS+=(--axis "${AXIS}")

${PY} "${SCRIPT_DIR}/stress_run.py" "${ARGS[@]}"
RC=$?

echo ""
echo "Done — results in ${OUT_DIR}/stress_results.json, logs in ${OUT_DIR}"
exit ${RC}
