#!/bin/bash
# ~/.panopticon/bin/heartbeat-hook  (PAN-800)
#
# Fires on Claude Code PostToolUse. POSTs agent.activity_changed(working, tool)
# to the dashboard, then records the cost event.
#
# Rewritten from the ~200-line jq read-modify-write version to a pure POST
# emitter. runtime.json and heartbeats/<id>.json are no longer written —
# AgentStateService's SubscriptionRef + projection_cache is canonical.
# activity.jsonl is retained as a forensic grep-able artifact (cheap to keep).
# The sessions.json append-only list is retained because it's a bookkeeping
# record of Claude session UUIDs, not runtime state.
# Cost-event recording stays on its own flock-serialized path.

set +e

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# shellcheck source=pan-hook-lib.sh
. "$SCRIPT_DIR/pan-hook-lib.sh" 2>/dev/null || exit 0

pan_resolve_agent_id || exit 0

TOOL_INFO=$(cat 2>/dev/null || echo '{}')

HAVE_JQ=0
if command -v jq >/dev/null 2>&1; then HAVE_JQ=1; fi

TOOL_NAME="unknown"
TOOL_INPUT=""
CLAUDE_SESSION_ID=""
if [ "$HAVE_JQ" = "1" ]; then
  TOOL_NAME=$(echo "$TOOL_INFO" | jq -r '.tool_name // "unknown"' 2>/dev/null || echo "unknown")
  TOOL_INPUT=$(echo "$TOOL_INFO" | jq -r '.tool_input | tostring | .[0:100] // ""' 2>/dev/null || echo "")
  CLAUDE_SESSION_ID=$(echo "$TOOL_INFO" | jq -r '.session_id // ""' 2>/dev/null || echo "")
fi

TS=$(date -Iseconds)

# ── Emit agent.activity_changed(working, tool) ─────────────────────────────
if [ "$HAVE_JQ" = "1" ]; then
  BODY=$(jq -n --arg tool "$TOOL_NAME" --arg ts "$TS" \
    '{kind: "activity", activity: "working", tool: $tool, timestamp: $ts}')
else
  BODY="{\"kind\":\"activity\",\"activity\":\"working\",\"tool\":\"$TOOL_NAME\",\"timestamp\":\"$TS\"}"
fi
pan_emit_event "$AGENT_ID" "$BODY"

# ── Activity log (retained for forensics) ─────────────────────────────────
AGENT_DIR="$HOME/.panopticon/agents/$AGENT_ID"
mkdir -p "$AGENT_DIR" 2>/dev/null
if [ "$HAVE_JQ" = "1" ]; then
  ENTRY=$(jq -n --arg ts "$TS" --arg tool "$TOOL_NAME" --arg action "$TOOL_INPUT" \
    '{ts: $ts, tool: $tool, action: $action}' 2>/dev/null || echo "")
  if [ -n "$ENTRY" ]; then
    echo "$ENTRY" >> "$AGENT_DIR/activity.jsonl" 2>/dev/null || true
    # Prune to last 100 entries.
    if [ -f "$AGENT_DIR/activity.jsonl" ]; then
      TMP="$AGENT_DIR/activity.jsonl.tmp"
      tail -n 100 "$AGENT_DIR/activity.jsonl" > "$TMP" 2>/dev/null \
        && mv "$TMP" "$AGENT_DIR/activity.jsonl" 2>/dev/null || true
    fi
  fi
fi

# ── Claude session history (append-only bookkeeping) ──────────────────────
if [ "$HAVE_JQ" = "1" ] && [ -n "$CLAUDE_SESSION_ID" ]; then
  SESSIONS_FILE="$AGENT_DIR/sessions.json"
  if [ -f "$SESSIONS_FILE" ]; then
    if ! jq -e --arg sid "$CLAUDE_SESSION_ID" 'any(.[]; . == $sid)' "$SESSIONS_FILE" >/dev/null 2>&1; then
      TMP="$SESSIONS_FILE.tmp"
      jq --arg sid "$CLAUDE_SESSION_ID" '. + [$sid]' "$SESSIONS_FILE" > "$TMP" 2>/dev/null \
        && mv "$TMP" "$SESSIONS_FILE" 2>/dev/null || true
    fi
  else
    echo "[\"$CLAUDE_SESSION_ID\"]" > "$SESSIONS_FILE" 2>/dev/null || true
  fi
fi

# ── Cost-event recording (unchanged, its own flock-serialized path) ──────
COST_SCRIPT=""
if [ -f "$HOME/.panopticon/bin/record-cost-event.js" ]; then
  COST_SCRIPT="$HOME/.panopticon/bin/record-cost-event.js"
elif [ -f "$SCRIPT_DIR/record-cost-event.js" ]; then
  COST_SCRIPT="$SCRIPT_DIR/record-cost-event.js"
fi

if [ -n "$COST_SCRIPT" ] && [ -n "$CLAUDE_SESSION_ID" ]; then
  GIT_BRANCH=$(git branch --show-current 2>/dev/null || echo "")
  WORKSPACE=$(pwd)

  if [ -z "$PANOPTICON_ISSUE_ID" ]; then
    if [[ "$GIT_BRANCH" =~ (pan|min|aud|krux|cli|PAN|MIN|AUD|KRUX|CLI)[-]([0-9]+) ]]; then
      PANOPTICON_ISSUE_ID="${BASH_REMATCH[1]^^}-${BASH_REMATCH[2]}"
    fi
  fi
  if [ -z "$PANOPTICON_ISSUE_ID" ]; then
    if [[ "$WORKSPACE" =~ (pan|min|aud|krux|cli|PAN|MIN|AUD|KRUX|CLI)[-]([0-9]+) ]]; then
      PANOPTICON_ISSUE_ID="${BASH_REMATCH[1]^^}-${BASH_REMATCH[2]}"
    fi
  fi
  export PANOPTICON_ISSUE_ID="${PANOPTICON_ISSUE_ID:-UNKNOWN}"
  export PANOPTICON_SESSION_TYPE="${PANOPTICON_SESSION_TYPE:-implementation}"

  STATE_DIR="$HOME/.panopticon/costs/state"
  mkdir -p "$STATE_DIR" 2>/dev/null
  LOCK_FILE="$STATE_DIR/${CLAUDE_SESSION_ID}.lock"
  {
    flock -x -w 30 200
    echo "$TOOL_INFO" | node "$COST_SCRIPT" 2>/dev/null || true
  } 200>"$LOCK_FILE"
fi

exit 0
