#!/usr/bin/env bash
# Update service catalog metadata in bulk from a JSON Lines file (one service per line).
#
#   ELOS_API=https://<your ELOS API address> ELOS_KEY=esk.… ./update-catalog.sh services.jsonl
#   DRY_RUN=1 ./update-catalog.sh services.jsonl     # show what would change, write nothing
#
# Each line names a service that already exists in ELOS (services arrive from your connected
# source control) and any catalog fields to set, for example:
#   {"service":"payments-api","tier":"tier-1","lifecycle":"production","system":"Payments Platform",
#    "tags":["payments","pci"],"metadata":{"cost-center":"CC-4020"},"owner":"Priya Raman"}
# "owner" is optional: the exact name of a person in ELOS, assigned as the service owner.
# Every other key is sent as a catalog patch; ELOS applies the editable fields and ignores the rest.
# The key needs a role with Edit service catalog (Engineering Manager works).
set -euo pipefail

: "${ELOS_API:?set ELOS_API to your ELOS API address}"
: "${ELOS_KEY:?set ELOS_KEY to a service account API key}"
FILE="${1:?usage: update-catalog.sh services.jsonl}"
command -v jq >/dev/null || { echo "jq is required" >&2; exit 1; }

call() {
  local method=$1 path=$2 body=${3:-} key=${4:-} out status
  for _ in 1 2 3 4 5; do
    out=$(curl -sS -w '\n%{http_code}' -X "$method" "$ELOS_API/v1$path" \
      -H "Authorization: Bearer $ELOS_KEY" -H "Content-Type: application/json" \
      ${key:+-H "Idempotency-Key: $key"} ${body:+--data "$body"})
    status=${out##*$'\n'}
    if [ "$status" = 429 ]; then sleep 2; continue; fi
    if [ "$status" -ge 400 ]; then echo "  $method $path failed ($status): ${out%$'\n'*}" >&2; return 1; fi
    printf '%s' "${out%$'\n'*}"
    return 0
  done
  echo "  $method $path: still rate limited" >&2; return 1
}

updated=0 missing=0 failed=0 n=0
while IFS= read -r line; do
  [ -z "${line// }" ] && continue
  n=$((n + 1))
  name=$(jq -r '.service // empty' <<<"$line")
  [ -z "$name" ] && { echo "line $n: no \"service\" key" >&2; failed=$((failed + 1)); continue; }
  q=$(jq -rn --arg v "$name" '$v|@uri')
  id=$(call GET "/services?q=$q&limit=50" | jq -r --arg n "$name" '.data[] | select(.name == $n) | .id' | head -1)
  if [ -z "$id" ]; then echo "skip  $name (no such service in ELOS)"; missing=$((missing + 1)); continue; fi

  patch=$(jq -c 'del(.service, .owner)' <<<"$line")
  owner=$(jq -r '.owner // empty' <<<"$line")
  if [ -n "${DRY_RUN:-}" ]; then echo "would update $name: $patch${owner:+ owner=$owner}"; continue; fi

  # One key per file line and content, so a re-run of the same file doesn't re-apply it.
  key="catalog-$(printf '%s' "$line" | shasum -a 256 | cut -c1-32)"
  if [ "$patch" != "{}" ] && ! call PUT "/services/$id/catalog" "$patch" "$key" >/dev/null; then failed=$((failed + 1)); continue; fi
  if [ -n "$owner" ]; then
    q=$(jq -rn --arg v "$owner" '$v|@uri')
    pid=$(call GET "/people?q=$q&limit=50" | jq -r --arg n "$owner" '.data[] | select(.name == $n) | .id' | head -1)
    if [ -z "$pid" ]; then echo "  $name: owner \"$owner\" isn't a person in ELOS; owner not changed" >&2
    else call PUT "/services/$id/owner" "$(jq -cn --arg id "$pid" --arg n "$owner" '{owner: {type: "person", id: $id, name: $n}}')" "$key-owner" >/dev/null || failed=$((failed + 1))
    fi
  fi
  echo "updated $name"; updated=$((updated + 1))
done < "$FILE"

echo "done: $updated updated, $missing not found, $failed failed"
[ "$failed" -eq 0 ]
