#!/usr/bin/env bash
# Regression suite: shared usage_agg module + workflow-usage-report Stop hook.
# Covers: format-drift gate (exact render_parts strings, color+plain), window
# accounting, watermark first-run-IS-reported, pre-watermark exclusion,
# journal-authoritative total, consolidated warning block, durable backstop,
# dedup, halted-run glyph, fail-open.
set -u
HERE="$(cd "$(dirname "$0")" && pwd)"
ROOTDIR="$(cd "$HERE/.." && pwd)"
HOOK="$HERE/workflow-usage-report.py"
STATUSLINE="$ROOTDIR/statusline-cost.sh"
PASS=0; FAIL=0
ok(){ PASS=$((PASS+1)); printf '  ok   %s\n' "$1"; }
bad(){ FAIL=$((FAIL+1)); printf '  FAIL %s\n' "$1"; }
TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT

# --- format-drift gate: exact render_parts output, the surface the status line
#     and hook share. A self-comparison only proves determinism; these golden
#     strings fail loudly if usage_agg rendering ever drifts. ---
python3 - "$ROOTDIR/lib" <<'PY'
import sys
sys.path.insert(0, sys.argv[1])
from usage_agg import render_parts, parse_files
import json, os, tempfile
fails=0
def check(name, cond):
    global fails
    print(("  ok   " if cond else "  FAIL ")+name)
    if not cond: fails+=1
pm={"opus":{"in":31000,"out":170000,"cache_read":7600000,"cache_write":1200000},
    "sonnet":{"in":492,"out":225000,"cache_read":32600000,"cache_write":1600000}}
plain=render_parts(pm, color=False)
check("render_parts opus plain exact", plain[0]=="Opus I:31k O:170k C:↓7.6M ↑1.2M hit:99%")
check("render_parts sonnet plain exact", plain[1]=="Sonnet I:492 O:225k C:↓32.6M ↑1.6M hit:99%")
col=render_parts(pm, color=True)
check("render_parts color carries ANSI + same detail",
      "\033[" in col[0] and "I:31k O:170k C:↓7.6M ↑1.2M hit:99%" in col[0])
# window accounting: only in-window assistant turns counted
d=tempfile.mkdtemp()
def a(m,ts,i,o,cr,cw): return json.dumps({"type":"assistant","timestamp":ts,"message":{"model":m,"usage":{"input_tokens":i,"output_tokens":o,"cache_read_input_tokens":cr,"cache_creation_input_tokens":cw}}})
p=os.path.join(d,"agent-x.jsonl")
open(p,"w").write("\n".join([
  a("claude-opus-4-8","2026-01-01T00:00:01.000Z",10,20,30,40),     # in
  a("claude-opus-4-8","2026-01-01T00:00:03.000Z",1,1,1,1),         # out (after)
  a("claude-sonnet-4-6","2025-12-31T23:59:59.000Z",5,5,5,5),       # out (before)
])+"\n")
w0=1767225600000.0  # 2026-01-01T00:00:00Z ms
per,_,_,_=parse_files([p], window=(w0, w0+2000))  # [00:00:00, 00:00:02]
check("window keeps in-bounds opus only", per=={"opus":{"in":10,"out":20,"cache_read":30,"cache_write":40}})
sys.exit(1 if fails else 0)
PY
[ $? -eq 0 ] && ok "usage_agg format-gate (above)" || bad "usage_agg format-gate (above)"

# --- status-line smoke: runs clean + deterministic on a real session if present ---
proj=/home/user/.claude/projects/-home-user--claude
fix_sid=""
for dd in "$proj"/*/subagents; do [ -d "$dd" ] && fix_sid="$(basename "$(dirname "$dd")")" && break; done
if [ -n "${fix_sid:-}" ] && [ -f "$proj/$fix_sid.jsonl" ]; then
  stdin=$(printf '{"transcript_path":"%s","session_id":"%s"}' "$proj/$fix_sid.jsonl" "$fix_sid")
  a=$(ANTHROPIC_BASE_URL="" printf '%s' "$stdin" | python3 "$STATUSLINE" 2>/dev/null)
  b=$(ANTHROPIC_BASE_URL="" printf '%s' "$stdin" | python3 "$STATUSLINE" 2>/dev/null)
  [ -n "$a" ] && [ "$a" = "$b" ] && ok "status-line deterministic + non-empty" || bad "status-line deterministic"
else
  printf '  skip status-line smoke (no fixture session)\n'
fi

# --- hook fixture: watermark semantics ---
sid=testsess; sess="$TMP/$sid"; mkdir -p "$sess/workflows" "$sess/subagents"
tp="$TMP/$sid.jsonl"; : > "$tp"
mkstdin(){ printf '{"transcript_path":"%s","session_id":"%s"}' "$tp" "$sid"; }

# A: first Stop, empty workflows dir -> watermark set, no output, no history dumped
outA=$(mkstdin | python3 "$HOOK")
[ -z "$outA" ] && ok "first Stop seeds watermark (no output)" || bad "first Stop no output"
python3 -c 'import json,sys; s=json.load(open(sys.argv[1])); sys.exit(0 if isinstance(s.get("watermark"),(int,float)) and s.get("settled")==[] else 1)' "$sess/.usage-reported.json" \
  && ok "state has watermark + empty settled" || bad "state watermark"

# Build the session's FIRST run AAA relative to the watermark, so its end >= W.
# This is the bug the seed-scheme missed: the first run must still be reported.
python3 - "$sess" <<'PY'
import sys,os,json
from datetime import datetime,timezone
sess=sys.argv[1]
W=json.load(open(os.path.join(sess,".usage-reported.json")))["watermark"]
DUR=3600000
def iso(ms): return datetime.fromtimestamp(ms/1000.0,tz=timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.000Z")
json.dump({"runId":"wf_AAA","status":"completed","durationMs":DUR,"startTime":W,"totalTokens":510919,"agentCount":16,
           "result":{"warnSummary":"WARNPILE line\n  session: deprecated-api.*  (# upstream pglite, unfixable)"}},
          open(os.path.join(sess,"workflows","wf_AAA.json"),"w"))
def a(m,ts,i,o,cr,cw): return {"type":"assistant","timestamp":ts,"message":{"model":m,"usage":{"input_tokens":i,"output_tokens":o,"cache_read_input_tokens":cr,"cache_creation_input_tokens":cw}}}
rows=[a("claude-opus-4-8",iso(W+1000),31000,170000,7600000,1200000),
      a("claude-sonnet-4-6",iso(W+2000),492,225000,32600000,1600000),
      a("claude-haiku-4-5",iso(W-50000),999,999,999,999),
      a("claude-haiku-4-5",iso(W+DUR+50000),888,888,888,888)]
open(os.path.join(sess,"subagents","agent-x.jsonl"),"w").write("".join(json.dumps(r)+"\n" for r in rows))
PY

# B: first run IS reported
outB=$(mkstdin | python3 "$HOOK")
msg=$(printf '%s' "$outB" | python3 -c 'import sys,json;print(json.load(sys.stdin)["systemMessage"])' 2>/dev/null)
case "$msg" in *"run wf_AAA ✓ 1h0m  16 agents"*) ok "FIRST run reported (run line+glyph+dur+agents)";; *) bad "first run reported";; esac
case "$msg" in *"Opus I:31k O:170k C:↓7.6M ↑1.2M hit:99%"*) ok "opus breakdown";; *) bad "opus breakdown";; esac
case "$msg" in *"Sonnet I:492 O:225k C:↓32.6M ↑1.6M hit:99%"*) ok "sonnet breakdown";; *) bad "sonnet breakdown";; esac
case "$msg" in *Haiku*) bad "haiku must be window-excluded";; *) ok "haiku excluded by time window";; esac
case "$msg" in *"total 510,919 tok"*) ok "journal-authoritative total";; *) bad "total";; esac
case "$msg" in *"upstream pglite"*) ok "consolidated warning block";; *) bad "warning block";; esac
[ -f "$sess/run-usage-wf_AAA.txt" ] && ok "durable backstop file written" || bad "durable file"

# C: dedup (settled)
outC=$(mkstdin | python3 "$HOOK")
[ -z "$outC" ] && ok "dedup (no re-report)" || bad "dedup"

# D: pre-watermark run excluded (end < W) but settled (not reloaded forever)
python3 - "$sess" <<'PY'
import sys,os,json
sess=sys.argv[1]
W=json.load(open(os.path.join(sess,".usage-reported.json")))["watermark"]
json.dump({"runId":"wf_OLD","status":"completed","durationMs":1000,"startTime":W-360000000,"totalTokens":10,"agentCount":1,"result":{}},
          open(os.path.join(sess,"workflows","wf_OLD.json"),"w"))
PY
outD=$(mkstdin | python3 "$HOOK")
[ -z "$outD" ] && ok "pre-watermark run excluded (no output)" || bad "pre-watermark excluded"
python3 -c 'import json,sys; s=json.load(open(sys.argv[1])); sys.exit(0 if "wf_OLD" in s.get("settled",[]) else 1)' "$sess/.usage-reported.json" \
  && ok "pre-watermark run settled (not reloaded)" || bad "pre-watermark settled"

# E: halted run (end >= W) reports with warn-glyph
python3 - "$sess" <<'PY'
import sys,os,json
sess=sys.argv[1]
W=json.load(open(os.path.join(sess,".usage-reported.json")))["watermark"]
json.dump({"runId":"wf_HALT","status":"halted","durationMs":5000,"startTime":W,"totalTokens":42,"agentCount":2,
           "result":{"warnSummary":"halted-warns"}},
          open(os.path.join(sess,"workflows","wf_HALT.json"),"w"))
PY
outH=$(mkstdin | python3 "$HOOK")
msgH=$(printf '%s' "$outH" | python3 -c 'import sys,json;print(json.load(sys.stdin)["systemMessage"])' 2>/dev/null)
case "$msgH" in *"run wf_HALT ⚠ 5s  2 agents"*) ok "halted run reported with ⚠ glyph";; *) bad "halted run";; esac

# fail-open
echo 'not json' | python3 "$HOOK" >/dev/null 2>&1 && ok "fail-open on garbage stdin" || bad "fail-open garbage"
printf '' | python3 "$HOOK" >/dev/null 2>&1 && ok "fail-open on empty stdin" || bad "fail-open empty"
printf '{"transcript_path":"%s","session_id":"nope"}' "$tp" | python3 "$HOOK" >/dev/null 2>&1 && ok "fail-open on missing session dir" || bad "fail-open missing dir"

echo "PASS=$PASS FAIL=$FAIL"
[ "$FAIL" -eq 0 ]
