#!/usr/bin/env bash
#
# health-probe.sh — manual verification that a humanwork service's /health or
# /ready endpoint is reachable, returns 200, and the response body status
# field matches the expected token.
#
# This is the same check the GitHub-Actions deploy gate runs after
# `aws ecs wait services-stable`. Use it locally after a Terraform change or
# manually to verify a deploy from outside CI.
#
# Usage:
#     bash agent/scripts/health-probe.sh <URL> [expected_status]
#
# Args:
#     URL              — full URL (with path) to probe. The script does NOT
#                        append /health; pass the exact endpoint.
#     expected_status  — optional token the JSON body's "status" field must
#                        contain. Defaults to "ok|ready" so the same probe
#                        works against the agent's /health ("status":"ok") and
#                        the api's /ready ("status":"ready"). Pass a single
#                        token (e.g. "ok") to tighten.
#
# Env:
#     HEALTH_PROBE_TIMEOUT — curl timeout in seconds (default 10).
#
# Exit codes:
#     0 — 200 with matching status token
#     1 — usage / arg error
#     2 — HTTP error (non-2xx, timeout, DNS, TLS)
#     3 — 200 response but body status token did not match
#
# Stdout is a one-line summary on success. On failure, stderr carries the
# diagnostic and the script exits non-zero — safe to use in CI gates.

set -u

if [[ $# -lt 1 || $# -gt 2 ]]; then
  echo "usage: $0 <url> [expected_status_token]" >&2
  echo "  e.g. $0 https://agent.h.work/health" >&2
  echo "  e.g. $0 https://api.h.work/ready ready" >&2
  exit 1
fi

URL="$1"
EXPECTED_STATUS="${2:-ok|ready}"
TIMEOUT="${HEALTH_PROBE_TIMEOUT:-10}"

# -m: max total time. -sS: silent but show errors. -w: print HTTP status to
# stdout. Curl writes %{http_code} to stdout via -w; any error message goes
# to stderr. We redirect stderr to a second tmp file so the captured
# HTTP_STATUS stays clean and we can surface the real diagnostic on failure.
RESPONSE_FILE="$(mktemp -t health-probe.XXXXXX)"
CURL_STDERR="$(mktemp -t health-probe-err.XXXXXX)"
trap 'rm -f "$RESPONSE_FILE" "$CURL_STDERR"' EXIT

if ! HTTP_STATUS="$(
  curl -sS -m "$TIMEOUT" -o "$RESPONSE_FILE" -w '%{http_code}' "$URL" 2>"$CURL_STDERR"
)"; then
  echo "ERROR: curl failed for $URL" >&2
  cat "$CURL_STDERR" >&2
  exit 2
fi

if [[ "$HTTP_STATUS" != "200" ]]; then
  echo "ERROR: $URL returned HTTP $HTTP_STATUS" >&2
  echo "--- response body ---" >&2
  cat "$RESPONSE_FILE" >&2
  exit 2
fi

BODY="$(cat "$RESPONSE_FILE")"

# Shape check: status field must contain one of the expected tokens. We
# avoid jq because this script runs on minimal containers (agent task, the
# deploy box, CI).
#
# EXPECTED_STATUS is a pipe-separated list of literal tokens (e.g. "ok" or
# "ok|ready"). We split on `|` and grep for each as a fixed string so a
# caller passing regex metacharacters (`.`, `.*`, etc.) cannot turn an
# unhealthy "degraded" / "error" body into a false success. This is a
# deliberate guard — the script is invoked from CI with operator-supplied
# values, regex injection here would let a misconfigured probe silently
# pass an unhealthy deploy.
matched=0
IFS='|' read -r -a _tokens <<<"$EXPECTED_STATUS"
for _tok in "${_tokens[@]}"; do
  if echo "$BODY" | grep -qF "\"status\":\"$_tok\""; then
    matched=1
    break
  fi
  # Also tolerate `"status": "tok"` (one space) — JSON serializers
  # sometimes pretty-print. Anything beyond that is non-canonical.
  if echo "$BODY" | grep -qF "\"status\": \"$_tok\""; then
    matched=1
    break
  fi
done

if [[ "$matched" != "1" ]]; then
  echo "ERROR: $URL returned 200 but body status did not match (${EXPECTED_STATUS})" >&2
  echo "--- response body ---" >&2
  echo "$BODY" >&2
  exit 3
fi

echo "ok: $URL -> HTTP 200, body: $BODY"
exit 0
