#!/usr/bin/env bash
# Synthetic records only. Keep UDS_RUN_ID unchanged to resume an uncertain request.
set -euo pipefail

: "${UDS_TOKEN:?Supply a scoped test credential through the environment.}"
: "${UDS_RUN_ID:?Supply a stable example-run identifier; keep it unchanged on retry.}"
[[ "$UDS_RUN_ID" =~ ^[a-zA-Z0-9_-]{1,64}$ ]] || { printf '%s\n' 'Invalid UDS_RUN_ID.' >&2; exit 1; }
for tool in curl jq; do
  command -v "$tool" >/dev/null || { printf 'Required command not found: %s.\n' "$tool" >&2; exit 1; }
done
UDS_BASE_URL="${UDS_BASE_URL:-https://api.redlineautohaus.com/api/v1/uds}"
UDS_BASE_URL="${UDS_BASE_URL%/}"
case "$UDS_BASE_URL" in https://*|http://localhost:*|http://127.0.0.1:*) ;; *) printf '%s\n' 'Use HTTPS (or explicit localhost for tests).' >&2; exit 1 ;; esac
fixture_path="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/fixtures.json"

request() {
  local method="$1" route="$2" step="${3:-}" body="${4:-}" response http_code
  local args=(--silent --show-error --connect-timeout 10 --max-time 35 --request "$method"
    --header "Authorization: Bearer $UDS_TOKEN" --header 'Accept: application/json, application/problem+json')
  if [[ "$method" == POST ]]; then
    args+=(--header 'Content-Type: application/json' --header "Idempotency-Key: docs:$UDS_RUN_ID:$step" --data-binary "$body")
  fi
  # No automatic fresh-key retry. Rerun with the same run ID after resolving an uncertain outcome.
  if ! response=$(curl "${args[@]}" --write-out $'\n%{http_code}' "$UDS_BASE_URL$route"); then
    printf 'Network outcome uncertain at %s. Resume with the same UDS_RUN_ID.\n' "$route" >&2
    return 1
  fi
  http_code="${response##*$'\n'}"
  response="${response%$'\n'*}"
  case "$http_code" in 200|201|202) ;;
    *) printf 'HTTP %s at %s. Inspect errors.md; preserve your keys.\n' "$http_code" "$route" >&2; return 1 ;;
  esac
  printf '%s' "$response" | jq -e '.'
}

request GET /capabilities >/dev/null
source_body=$(jq --arg key "docs-$UDS_RUN_ID-source" '.source + {external_key:$key}' "$fixture_path")
source_id=$(request POST /sources source "$source_body" | jq -er '.id')
session_body=$(jq -nc --arg key "docs-$UDS_RUN_ID-session" '{external_key:$key,label:"Synthetic unidentified documentation session"}')
session_id=$(request POST /sessions session "$session_body" | jq -er '.id')
request POST "/sessions/$session_id/sources" session-source "$(jq -nc --arg id "$source_id" '{source_id:$id}')" >/dev/null
evidence_body=$(jq --arg id "$source_id" '.source_record + {source_id:$id,external_key:"synthetic-note-001"}' "$fixture_path")
evidence_id=$(request POST /source-records evidence "$evidence_body" | jq -er '.id')
message_body=$(jq --arg session "$session_id" --arg evidence "$evidence_id" '.complete_message + {session_id:$session,source_record_id:$evidence}' "$fixture_path")
message_id=$(request POST /messages complete "$message_body" | jq -er '.id')
replay_id=$(request POST /messages complete "$message_body" | jq -er '.id')
[[ "$message_id" == "$replay_id" ]] || { printf '%s\n' 'Replay returned a different ID.' >&2; exit 1; }
request GET "/messages/$message_id" | jq -e '.payload.representation == "complete" and .payload.payload_hex == "22F186"' >/dev/null

partial_body=$(jq --arg session "$session_id" --arg evidence "$evidence_id" '.partial_message + {session_id:$session,source_record_id:$evidence}' "$fixture_path")
partial_id=$(request POST /messages partial "$partial_body" | jq -er '.id')
request GET "/messages/$partial_id" | jq -e '.payload.representation == "partial" and .payload.segments[0].offset_bytes == 0 and .payload.segments[0].payload_hex == "623F06"' >/dev/null

unavailable_body=$(jq --arg session "$session_id" --arg evidence "$evidence_id" '.unavailable_message + {session_id:$session,source_record_id:$evidence}' "$fixture_path")
unavailable_id=$(request POST /messages unavailable "$unavailable_body" | jq -er '.id')
request GET "/messages/$unavailable_id" | jq -e '.payload.representation == "unavailable" and (.payload | has("payload_hex") | not) and (.payload | has("segments") | not)' >/dev/null

import_body=$(jq -nc --arg key "docs-$UDS_RUN_ID-import" '{client_namespace:"example.uds-docs",external_key:$key,purpose:"Synthetic documentation mixed outcomes"}')
import_id=$(request POST /imports import "$import_body" | jq -er '.id')
batch_body=$(jq -nc --argjson message "$message_body" '{batch_key:"synthetic-batch-001",items:[$message,($message + {external_record_key:"synthetic-batch-created-001",source_order:"3"}),($message + {external_record_key:"synthetic-invalid-001",payload:{representation:"complete",payload_hex:"22F18"}})]}')
batch_id=$(request POST "/imports/$import_id/message-batches" batch "$batch_body" | jq -er '.id')
request POST "/imports/$import_id/finalize" finalize '{}' >/dev/null

batch_status=queued
for ((poll=0; poll<60; poll++)); do
  batch_status=$(request GET "/imports/$import_id/message-batches/$batch_id" | jq -er '.status')
  case "$batch_status" in completed|completed_with_errors|failed|cancelled) break ;; esac
  sleep 2
done
jq -nc --arg source "$source_id" --arg session "$session_id" --arg message "$message_id" --arg partial "$partial_id" --arg unavailable "$unavailable_id" --arg import "$import_id" --arg batch "$batch_id" --arg status "$batch_status" '{source_id:$source,session_id:$session,message_id:$message,partial_message_id:$partial,unavailable_message_id:$unavailable,import_id:$import,batch_id:$batch,bytes_verified:true,replay_verified:true,batch_status:$status}'
if [[ "$batch_status" != completed_with_errors ]]; then
  printf 'Batch status is %s. Preserve IDs and inspect/poll outcomes; completion is not assumed.\n' "$batch_status" >&2
  exit 2
fi
request GET "/imports/$import_id/message-batches/$batch_id" | jq -e '.counts.created == 1 and .counts.existing == 1 and .counts.rejected == 1 and .counts.processed == 3' >/dev/null
request GET "/imports/$import_id/message-batches/$batch_id/items?limit=100" | jq -e --arg id "$message_id" '.has_more == false and (.data | length) == 3 and [.data[].status] == ["existing","created","rejected"] and .data[0].resource_id == $id and .data[2].outcome.status == 422' >/dev/null
printf '%s\n' 'Verified all three batch outcomes: existing, created and rejected.'
