#!/usr/bin/env bash
# log-metric.sh  -  append a single event to the pipeline metrics log.
#
# Append-only JSONL at $METRICS_FILE (default $HOME/.claude/logs/multi-agent/metrics.jsonl).
# One event per line. Schema:
#   {
#     "ts":      "<ISO 8601 timestamp>",
#     "task_id": "<jira id, github issue, or run id>",
#     "phase":   "<0..7>",
#     "event":   "<event name>",
#     "details": { ...arbitrary key/value pairs... }
#   }
#
# Usage:
#   log-metric.sh <task_id> <phase> <event> [key=value ...]
#
# Examples:
#   log-metric.sh PROJ-1234 4 review.completed raw_count=8 accepted=3 deferred=2 rejected=3 approved=true duration_ms=42000
#   log-metric.sh PROJ-1234 4 triage.edge_case case=high-rejection-rate
#   log-metric.sh PROJ-1234 3 rework.started iteration=2 accepted_blocking=2
#   log-metric.sh #316 7 task.completed phases=8 review_cycles=2 lang=tr
#
# Atomic append: each call uses `>> "$file"` which the kernel guarantees
# atomic for writes ≤ PIPE_BUF (4 KB on macOS/Linux). One JSONL line is well
# under that limit, so concurrent pipeline runs don't interleave.
#
# Failure mode: if the metrics directory is unwritable, we WARN to stderr but
# do NOT fail the pipeline. Telemetry is best-effort, never load-bearing.

set -uo pipefail

if [ "$#" -lt 3 ]; then
  echo "usage: log-metric.sh <task_id> <phase> <event> [key=value ...]" >&2
  exit 64
fi

TASK_ID="$1"; shift
PHASE="$1"; shift
EVENT="$1"; shift

METRICS_FILE="${METRICS_FILE:-$HOME/.claude/logs/multi-agent/metrics.jsonl}"
METRICS_DIR="$(dirname "$METRICS_FILE")"

mkdir -p "$METRICS_DIR" 2>/dev/null || {
  echo "warn: log-metric: cannot create $METRICS_DIR  -  telemetry skipped" >&2
  exit 0
}

# Build details object from key=value args. Keep it shell-portable: no jq required.
DETAILS="{"
SEP=""
for kv in "$@"; do
  KEY="${kv%%=*}"
  VAL="${kv#*=}"
  # Decide if value is bool / int / string. Keep simple  -  anything not parseable as
  # int or true/false becomes a JSON string.
  case "$VAL" in
    true|false) JSON_VAL="$VAL" ;;
    ''|*[!0-9]*) JSON_VAL="\"$(printf '%s' "$VAL" | tr -d '\n\r' | sed 's/\\/\\\\/g; s/"/\\"/g; s/	/\\t/g')\"" ;;
    *) JSON_VAL="$VAL" ;;
  esac
  DETAILS="${DETAILS}${SEP}\"${KEY}\":${JSON_VAL}"
  SEP=","
done
DETAILS="${DETAILS}}"

TS="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
LINE="{\"ts\":\"${TS}\",\"task_id\":\"${TASK_ID}\",\"phase\":\"${PHASE}\",\"event\":\"${EVENT}\",\"details\":${DETAILS}}"

# Atomic append (one line, well under PIPE_BUF).
echo "$LINE" >> "$METRICS_FILE" 2>/dev/null || {
  echo "warn: log-metric: cannot write to $METRICS_FILE  -  telemetry skipped" >&2
  exit 0
}

# v8.3+ opt-in tracker forwarder. When LOG_METRIC_FORWARD_TO_TRACKER=1 and the
# event details carry tokens_in / tokens_out, mirror them into phase-tracker.sh
# so the cost block stays in sync with metrics.jsonl from a single call site.
# Best-effort: never fails the pipeline.
if [ "${LOG_METRIC_FORWARD_TO_TRACKER:-0}" = "1" ]; then
  TI=""; TO=""; TC=""; MODEL=""
  for kv in "$@"; do
    case "${kv%%=*}" in
      tokens_in)     TI="${kv#*=}" ;;
      tokens_out)    TO="${kv#*=}" ;;
      tokens_cached) TC="${kv#*=}" ;;
      model)         MODEL="${kv#*=}" ;;
    esac
  done
  if [ -n "$TI" ] && [ -n "$TO" ]; then
    SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
    # Sanitize the optional cached count: a non-integer (quoted, float, empty)
    # must NOT poison the whole tokens call and lose the valid in/out counts.
    # phase-tracker rejects the call on any bad arg, so drop a bad cached to 0.
    case "$TC" in
      ''|*[!0-9]*) TC=0 ;;
    esac
    if [ -x "$SCRIPT_DIR/phase-tracker.sh" ]; then
      # tokens_cached is optional (4th arg); when the host reports prompt-cache
      # reads, forwarding it lets the cost ledger price them at the cheaper rate.
      TRACKER_QUIET=1 "$SCRIPT_DIR/phase-tracker.sh" tokens "$PHASE" "$TI" "$TO" "$TC" >/dev/null 2>&1 || true
      if [ -n "$MODEL" ]; then
        TRACKER_QUIET=1 "$SCRIPT_DIR/phase-tracker.sh" model "$PHASE" "$MODEL" >/dev/null 2>&1 || true
      fi
    fi
  fi
fi
