#!/usr/bin/env bash
# cURL + jq, Bash/Git Bash. Exactly one request, no redirects/retries.
# bash conversation.sh saved-request.json NEW-private-response-directory
set -euo pipefail
umask 077
[[ $# == 2 ]] || { echo 'Usage: bash conversation.sh saved-request.json NEW-response-directory' >&2; exit 2; }
intent=$1
destination=$2
base=$(jq -er '.base_url' "$intent")
path=$(jq -er '.path' "$intent")
method=$(jq -er '.method' "$intent")
assignment=$(jq -er '.assignment_id' "$intent")
subject=$(jq -er '.external_user_id' "$intent")
operation=$(jq -r '.idempotency_key // ""' "$intent")
[[ $base =~ ^https://[A-Za-z0-9.-]+(:[0-9]+)?/v1/?$ ]] || { echo 'Invalid API base' >&2; exit 2; }
[[ $path =~ ^/(chat|requests/[A-Za-z0-9_-]+|sessions(/[A-Za-z0-9_-]+(/(end|discard|history))?)?|session/status|data/(export|erase)|conversation/(catalog|insights|voice|data/export|sessions(/[A-Za-z0-9_-]+(/(consent|playback|debrief|audio))?)?|audio/[A-Za-z0-9_-]+(/(continue|segments/[A-Za-z0-9_-]+))?))$ ]] || { echo 'Invalid API path' >&2; exit 2; }
uuid='^[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}$'
[[ $assignment =~ $uuid && $method =~ ^(GET|POST|DELETE)$ ]] || exit 2
[[ -n $subject && ${#subject} -le 200 && $subject != *$'\n'* && $subject != *$'\r'* ]] || exit 2
[[ ${FOREVERLEARNING_API_KEY:-} =~ ^[[:graph:]]{1,512}$ ]] || { echo 'Set the server-held key in FOREVERLEARNING_API_KEY' >&2; exit 2; }
[[ $method == GET || $operation =~ $uuid ]] || { echo 'Save an operation UUID first' >&2; exit 2; }
jq -e '(.query // {}) | keys | all(. == "limit" or . == "cursor" or . == "session_id")' "$intent" >/dev/null
query=$(jq -r '(.query // {}) | to_entries | map((.key|@uri)+"="+(.value|tostring|@uri)) | join("&")' "$intent")
url=${base%/}$path
[[ -z $query ]] || url=$url?$query
# Reserve the entire output directory before any request; never overwrite a receipt.
mkdir -- "$destination"
headers=$destination/request-headers.private
trap 'rm -f -- "$headers"' EXIT
printf 'Authorization: Bearer %s\nX-Assignment-Id: %s\nX-User-Id: %s\n' "$FOREVERLEARNING_API_KEY" "$assignment" "$subject" >"$headers"
args=(--silent --show-error --proto '=https' --max-time 120 --max-filesize 8388608 --request "$method" --header "@$headers"
  --dump-header "$destination/response.headers" --output "$destination/response.raw" --write-out '%{http_code}')
if [[ $method != GET ]]; then
  printf 'Content-Type: application/json\nIdempotency-Key: %s\n' "$operation" >>"$headers"
  jq -c '.body // {}' "$intent" >"$destination/request-body.private"
  [[ $(wc -c <"$destination/request-body.private") -le 49152 ]] || exit 2
  args+=(--data-binary "@$destination/request-body.private")
fi
# A nonzero curl result or an error frame is ambiguous, even if some text arrived.
curl "${args[@]}" --url "$url" >"$destination/http-status"
status=$(cat "$destination/http-status")
[[ $status =~ ^2[0-9][0-9]$ ]] || { echo "HTTP $status; retain the saved request and inspect its request ID" >&2; exit 1; }
echo 'Transport finished. Verify JSON status or the final SSE receipt before another operation.'
