#!/usr/bin/env bash
# render-cost-summary.sh  -  v6.1.J
#
# Reads phase-tracker state + cost-table.json, prints the "### Cost Summary"
# markdown section to stdout. Consumed by /multi-agent:channels when
# `reportContent.costSummary === true`.
#
# Usage: render-cost-summary.sh <task-id> [--otel-spans <path>]
#
# Exit codes:
#   0  -  table rendered (empty table still prints with header + "no data" row)
#   2  -  tracker JSON missing AND spans file missing (caller should skip section)

set -euo pipefail

TASK_ID="${1:?usage: render-cost-summary.sh <task-id> [--otel-spans <path>]}"
shift || true

SPANS_FILE=""
while [ $# -gt 0 ]; do
  case "$1" in
    --otel-spans) SPANS_FILE="${2:-}"; shift 2 ;;
    *) shift ;;
  esac
done

# cost-table.json/cost-lib.sh ship as siblings of this script both in the
# repo (pipeline/scripts/) and once installed (~/.claude/scripts/) - a
# repo-root-relative path (../../pipeline/scripts/...) only resolves in the
# repo checkout and silently misses in the installed layout. Match
# phase-tracker.sh's own resolution instead of re-deriving a repo root.
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
COST_TABLE="$SCRIPT_DIR/cost-table.json"
COST_LIB="$SCRIPT_DIR/cost-lib.sh"
if [ -f "$COST_LIB" ]; then . "$COST_LIB"; else COST_JQ_DEFS=""; fi

command -v jq >/dev/null 2>&1 || { echo "render-cost-summary: jq required" >&2; exit 2; }

# Tracker JSON candidates, worktree convention first, then the location
# phase-tracker.sh actually writes ($HOME/.claude/logs/multi-agent/<task>/
# tracker-state.json). The list must stay in lockstep with
# render-agent-log-cost.sh - before the logs/ candidates were added here,
# every standard run exited 2 and the channels Cost Summary silently never
# rendered, because only the worktree paths were tried.
tracker_file=""
task_id_bare="${TASK_ID##*-}"
for candidate in \
  "$PWD/.worktrees/$TASK_ID/phase-tracker.json" \
  "$PWD/.worktrees/$task_id_bare/phase-tracker.json" \
  "$PWD/.worktrees/task-$task_id_bare/phase-tracker.json" \
  "$HOME/.claude/logs/multi-agent/$TASK_ID/tracker-state.json" \
  "$HOME/.claude/logs/multi-agent/$task_id_bare/tracker-state.json"
do
  [ -f "$candidate" ] && { tracker_file="$candidate"; break; }
done

if [ -z "$tracker_file" ] && [ -z "$SPANS_FILE" ]; then
  exit 2
fi

# Build rows  -  prefer tracker JSON, fall back to spans aggregation
rows_json="[]"
if [ -n "$tracker_file" ]; then
  # Tracker JSON ships in two shapes (same contract as render-agent-log-cost.sh):
  #   array shape   -  phase-tracker.sh writes phases:[{id, name, model, tokens_in, ...}]
  #   object shape  -  older fixture / hand-built variant phases:{ "1": {...}, ... }
  rows_json=$(jq '
    (if (.phases | type) == "array" then
      [.phases[] | {key: (.id | tostring), value: .}]
    else
      (.phases // {} | to_entries)
    end)
    | [ .[] |
        select(.value.tokens_in // 0 > 0 or .value.tokens_out // 0 > 0) |
        {
          phase: .key,
          phase_name: (.value.name // .key),
          model: (.value.model // " - "),
          tokens_in: (.value.tokens_in // 0),
          tokens_out: (.value.tokens_out // 0),
          tokens_cached: (.value.tokens_cached // 0)
        }
      ]
    | sort_by(.phase | tonumber? // 999)' "$tracker_file")
fi

if [ "$rows_json" = "[]" ] && [ -n "$SPANS_FILE" ] && [ -f "$SPANS_FILE" ]; then
  rows_json=$(jq -s '
    [ .[] | select(.name | startswith("phase.tokens")) ] |
    group_by(.attributes.phase_id // .attributes.phase // "?") |
    map({
      phase: (.[0].attributes.phase_id // .[0].attributes.phase // "?"),
      phase_name: (.[0].attributes.phase_name // (.[0].attributes.phase_id // "?")),
      model: (.[0].attributes.model // " - "),
      tokens_in: ([.[].attributes.tokens_in_delta // 0] | add),
      tokens_out: ([.[].attributes.tokens_out_delta // 0] | add),
      tokens_cached: ([.[].attributes.tokens_cached_delta // 0] | add)
    })
  ' "$SPANS_FILE")
fi

# Compute USD per row using cost-table
joined=$(jq -n --argjson rows "$rows_json" --slurpfile prices "$COST_TABLE" "$COST_JQ_DEFS"'
  $rows | map(
    . as $r |
    ($prices[0].prices[$r.model] // null) as $p |
    . + {
      usd: cost_usd_of($p; $r.tokens_in; $r.tokens_out; ($r.tokens_cached // 0))
    }
  )
')

totals=$(jq -n --argjson rows "$joined" '
  {
    tokens_in:  ($rows | map(.tokens_in)  | add // 0),
    tokens_out: ($rows | map(.tokens_out) | add // 0),
    usd:        ($rows | map(select(.usd != null) | .usd) | add),
    any_missing_usd: ($rows | map(.usd == null) | any)
  }
')

# Render markdown
printf '### Cost Summary\n'
printf '| Phase | Model | Tokens in | Tokens out | Est. USD |\n'
printf '|-------|-------|-----------|------------|----------|\n'

n_rows=$(jq 'length' <<< "$joined")
if [ "$n_rows" = "0" ]; then
  printf '| *(no tracker data for %s)* |  -  |  -  |  -  |  -  |\n' "$TASK_ID"
  exit 0
fi

jq -r '.[] |
  [
    (.phase_name // .phase),
    .model,
    (.tokens_in  | tostring | (if (length > 3) then [splits("(?=(\\d{3})+$)")] | map(select(. != "")) | join(",") else . end)),
    (.tokens_out | tostring | (if (length > 3) then [splits("(?=(\\d{3})+$)")] | map(select(. != "")) | join(",") else . end)),
    (if .usd == null then " - " else "$" + ((.usd * 100 | floor) / 100 | tostring) end)
  ] | "| " + join(" | ") + " |"
' <<< "$joined"

ti=$(jq -r '.tokens_in  | tostring | (if (length > 3) then [splits("(?=(\\d{3})+$)")] | map(select(. != "")) | join(",") else . end)' <<< "$totals")
to=$(jq -r '.tokens_out | tostring | (if (length > 3) then [splits("(?=(\\d{3})+$)")] | map(select(. != "")) | join(",") else . end)' <<< "$totals")
usd_total=$(jq -r 'if .usd == null then " - " else "$" + ((.usd * 100 | floor) / 100 | tostring) end' <<< "$totals")
missing=$(jq -r '.any_missing_usd' <<< "$totals")

printf '| **Total** |  | **%s** | **%s** | **%s** |\n' "$ti" "$to" "$usd_total"

if [ "$missing" = "true" ]; then
  printf '\n*USD unavailable for one or more rows  -  add model to `pipeline/scripts/cost-table.json`.*\n'
fi

exit 0
