#!/bin/sh
# atc-emit: report an event to Agentic Traffic Control.
#
#   atc-emit <type> [options] [key=value ...] [key:=json ...]
#   atc-emit check            test the connection and token
#   atc-emit inbox            print answers and verdicts the human sent this agent
#
# Payload fields are given as key=value (a string) or key:=json (a number, boolean or array):
#
#   atc-emit decision.made summary="Use sqlx, not diesel" rationale="Already in the workspace" \
#            alternatives:='["diesel","sea-orm"]'
#   atc-emit question.raised question="Split the crate or keep a module?" urgency=high \
#            options:='["split","module"]' recommendation=split meanwhile=waiting
#   atc-emit blocker.hit cause=flaky_test description="lobby::reconnect fails 1 in 4"
#
# Options:
#   --ticket ID     the ticket (default $ATC_TICKET)
#   --branch NAME   the branch (default: the current git branch)
#   --pr N          the pull request number
#   --link REL=URL  add a link (repeatable): pr, ci, session, ticket, doc...
#   --json OBJECT   the whole payload as JSON, instead of key=value pairs
#   --id ID         the event id (default: generated); resending an id is a no-op
#   --dry-run       print the event instead of sending it
#
# Environment: ATC_TOKEN (required), ATC_URL (default https://agentictrafficcontrol.com),
# ATC_SESSION_ID (set by the SessionStart hook), ATC_AGENT_NAME, ATC_RUNTIME, ATC_TICKET.
#
# Reporting is best-effort: without a token, or if the tower is unreachable, this prints a
# warning and exits 0, so it never derails the work.
set -u
ATC_URL="${ATC_URL:-https://agentictrafficcontrol.com}"

warn() { printf 'atc-emit: %s\n' "$*" >&2; }

# JSON-escape a string (backslash, quote, and control characters).
js() {
  printf '%s' "$1" | awk 'BEGIN { ORS = "" } {
    gsub(/\\/, "\\\\"); gsub(/"/, "\\\""); gsub(/\t/, "\\t"); gsub(/\r/, "\\r");
    if (NR > 1) printf "\\n"; printf "%s", $0 }'
}

need_token() {
  if [ -z "${ATC_TOKEN:-}" ]; then
    warn "ATC_TOKEN is not set; event not sent (see $ATC_URL/docs/connect)"
    exit 0
  fi
}

agent_id() {
  if [ -n "${ATC_SESSION_ID:-}" ]; then printf '%s' "$ATC_SESSION_ID"
  elif [ -n "${CLAUDE_SESSION_ID:-}" ]; then printf '%s' "$CLAUDE_SESSION_ID"
  elif [ -n "${ATC_AGENT_ID:-}" ]; then printf '%s' "$ATC_AGENT_ID"
  else printf '%s-%s' "$(hostname 2>/dev/null || echo agent)" "$PPID"
  fi
}

case "${1:-}" in
  ""|-h|--help)
    sed -n '2,30p' "$0" | sed 's/^# \{0,1\}//'
    exit 0 ;;
  check)
    need_token
    curl -sS -m 10 -H "Authorization: Bearer $ATC_TOKEN" "$ATC_URL/v1/ping"; echo
    exit $? ;;
  inbox)
    need_token
    curl -sS -m 10 -G -H "Authorization: Bearer $ATC_TOKEN" \
      --data-urlencode "agent=$(agent_id)" --data-urlencode "after=${2:-0}" "$ATC_URL/v1/inbox"; echo
    exit 0 ;;
esac

type="$1"; shift
ticket="${ATC_TICKET:-}"; branch=""; pr=""; links=""; payload_json=""; fields=""; id=""; dry=0
branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)
[ "$branch" = "HEAD" ] && branch=""

while [ $# -gt 0 ]; do
  case "$1" in
    --ticket) ticket="$2"; shift 2 ;;
    --branch) branch="$2"; shift 2 ;;
    --pr) pr="$2"; shift 2 ;;
    --link)
      rel="${2%%=*}"; href="${2#*=}"
      links="$links${links:+,}{\"rel\":\"$(js "$rel")\",\"href\":\"$(js "$href")\"}"
      shift 2 ;;
    --json) payload_json="$2"; shift 2 ;;
    --id) id="$2"; shift 2 ;;
    --dry-run) dry=1; shift ;;
    *:=*) key="${1%%:=*}"; fields="$fields${fields:+,}\"$(js "$key")\":${1#*:=}"; shift ;;
    *=*) key="${1%%=*}"; fields="$fields${fields:+,}\"$(js "$key")\":\"$(js "${1#*=}")\""; shift ;;
    *) warn "unexpected argument: $1 (fields are key=value or key:=json)"; exit 2 ;;
  esac
done

[ -n "$payload_json" ] || payload_json="{$fields}"
[ -n "$id" ] || id="atc-$(date +%s)-$(od -An -N6 -tx1 /dev/urandom | tr -d ' \n')"
now=$(date -u +%Y-%m-%dT%H:%M:%SZ)

agent="{\"id\":\"$(js "$(agent_id)")\",\"runtime\":\"$(js "${ATC_RUNTIME:-claude-code}")\""
[ -n "${ATC_AGENT_NAME:-}" ] && agent="$agent,\"name\":\"$(js "$ATC_AGENT_NAME")\""
agent="$agent}"

body="{\"schema\":\"atc.event/v1\",\"id\":\"$(js "$id")\",\"type\":\"$(js "$type")\",\"occurred_at\":\"$now\",\"agent\":$agent"
[ -n "$ticket" ] && body="$body,\"ticket\":{\"id\":\"$(js "$ticket")\"}"
if [ -n "$branch" ] || [ -n "$pr" ]; then
  repo=""
  [ -n "$branch" ] && repo="\"branch\":\"$(js "$branch")\""
  [ -n "$pr" ] && repo="$repo${repo:+,}\"pr\":$pr"
  body="$body,\"repo\":{$repo}"
fi
[ -n "$links" ] && body="$body,\"links\":[$links]"
body="$body,\"payload\":$payload_json}"

if [ "$dry" = 1 ]; then printf '%s\n' "$body"; exit 0; fi
need_token

out=$(printf '%s' "$body" | curl -sS -m 10 --retry 2 --retry-connrefused -w '\n%{http_code}' -X POST \
  -H 'Content-Type: application/json' -H "Authorization: Bearer $ATC_TOKEN" \
  --data-binary @- "$ATC_URL/v1/events" 2>&1) || { warn "could not reach $ATC_URL; event not sent"; exit 0; }
code=$(printf '%s' "$out" | tail -n 1)
resp=$(printf '%s' "$out" | sed '$d')
case "$code" in
  2*) printf 'sent %s (%s)\n' "$type" "$id" ;;
  *) warn "HTTP $code: $resp"; exit 1 ;;
esac
