#!/usr/bin/env bash
set -euo pipefail

LOG=/tmp/tuple-trigger-debug.log
{
    printf '\n=== %s call-transcription-complete fired (claude-transcript-summary) ===\n' "$(date -u +%FT%TZ)"
    printf 'cwd=%s pid=%s ppid=%s\n' "$(pwd)" "$$" "$PPID"
    printf 'argv: %s\n' "$*"
    printf 'env (filtered):\n'
    env | grep -E '^(HOME|USER|PATH|TUPLE_|CURRENT_USER_)' | sort
} >> "$LOG" 2>&1
trap 'printf "exit status=%s on line %s\n" "$?" "$LINENO" >> "$LOG"' EXIT

exec >>"$LOG" 2>&1

if [ -z "${TUPLE_TRIGGER_CALL_ARTIFACTS_DIRECTORY:-}" ]; then
    echo "claude-transcript-summary: TUPLE_TRIGGER_CALL_ARTIFACTS_DIRECTORY was not set" >&2
    exit 1
fi

TRANSCRIPTION_DIR="${TUPLE_TRIGGER_CALL_ARTIFACTS_DIRECTORY}"
if [ ! -d "${TRANSCRIPTION_DIR}" ]; then
    echo "claude-transcript-summary: transcription directory does not exist: ${TRANSCRIPTION_DIR}" >&2
    exit 1
fi

SESSION_DIR="$(basename "${TRANSCRIPTION_DIR}")"
PARENT_DIR="$(dirname "${TRANSCRIPTION_DIR}")"
PARENT_NAME="$(basename "${PARENT_DIR}")"
if [[ "${SESSION_DIR}" == *"@"* ]]; then
    CALL_ID="${SESSION_DIR##*@}"
elif [[ "${PARENT_NAME}" =~ ^[0-9A-Fa-f-]{8,}$ ]]; then
    CALL_ID="${PARENT_NAME}"
else
    CALL_ID="${SESSION_DIR}"
fi

PID_FILE="${TRANSCRIPTION_DIR}/claude-summary.pid"
PROMPT_FILE="${TRANSCRIPTION_DIR}/claude-summary-prompt.md"
# Set your preferred terminal here, or leave empty to auto-detect.
# One of: ghostty | iterm | alacritty | terminal
# (Also overridable from the environment: PREFERRED_TERM=iterm)
PREFERRED_TERM="${PREFERRED_TERM:-}"
LAUNCHER_FILE="${TRANSCRIPTION_DIR}/launch-claude-summary.command"
TRIGGER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
WATCHER_SRC="${TRIGGER_DIR}/tuple-call-watcher.py"
WATCHER_DST="${TRANSCRIPTION_DIR}/tuple-call-watcher.py"

if [ -f "${PID_FILE}" ] && kill -0 "$(cat "${PID_FILE}" 2>/dev/null)" 2>/dev/null; then
    echo "claude-transcript-summary: Claude summary already running for ${TRANSCRIPTION_DIR}"
    exit 0
fi

# Ship the fixed transcript watcher so the summary reads the backlog
# deterministically via --catchup instead of hand-reading the JSONL files.
if [ -f "${WATCHER_SRC}" ]; then
    cp "${WATCHER_SRC}" "${WATCHER_DST}"
    chmod 0755 "${WATCHER_DST}"
else
    echo "claude-transcript-summary: watcher not found at ${WATCHER_SRC}" >&2
    exit 1
fi

{
    cat <<'PROMPT'
You are summarizing a completed Tuple pair-programming transcription. Your working directory is the Tuple transcription directory opened by this trigger.

PROMPT
    printf 'The trigger fired for:\n\n'
    printf -- '- Transcription directory: %s\n' "${TRANSCRIPTION_DIR}"
    printf -- '- Session directory name: %s\n' "${SESSION_DIR}"
    printf -- '- Inferred call id: %s\n' "${CALL_ID}"
    cat <<'PROMPT'

The current directory should contain `events.jsonl` and `transcriptions.jsonl`, one JSON record per line. Other call participants do not see your output; you interact only with the user at this terminal.

## Goal

Read the full transcript (see How to read the transcript), then immediately produce a tight, useful call summary. This is a completed-transcription trigger: run the watcher once in `--catchup` mode to read the backlog — do not start a live or continuous watch.

## File schemas

| File | Fields | Notes |
| --- | --- | --- |
| `events.jsonl` | `category, message, time, user?` | Categories commonly include `recording_started`, `recording_stopped`, `user_joined`, `user_left`, `user_audio_started`, `user_audio_stopped`, and `call_ended`. |
| `transcriptions.jsonl` | `start, end, text, user_id` | Resolve `user_id` to a name from `user_joined` events when available. |

If a field looks unfamiliar, inspect a few records and adapt rather than assuming.

## How to read the transcript

Tuple ships a fixed watcher script in this directory. Read the whole call by running it once in catch-up mode:

    ./tuple-call-watcher.py --catchup

It prints every record across all of this call's session directories (including any mid-call restarts) as tagged lines:

    T|<session-dir>|<json-record>   a transcriptions.jsonl record
    E|<session-dir>|<json-record>   an events.jsonl record

Parse the `<json-record>` portion of each. Build a speaker map from `user_joined` events; the watcher already drops the noisy `user_audio_started`/`user_audio_stopped` events. Use timestamps when they help anchor decisions, action items, or follow-up questions. (The raw `events.jsonl` / `transcriptions.jsonl` files are still here if you want to read one directly.)

## Output

Produce the summary first, without preamble. Use this shape:

## Summary

2-4 bullets covering the main outcome of the conversation.

## Decisions

Bullets for concrete decisions. Omit this section if there were none.

## Action items

Bullets with owner names when stated. Omit this section if there were none.

## Open questions

Bullets for unresolved questions or follow-ups. Omit this section if there were none.

## Notable context

Only include details that would help the user remember the call later. Omit this section if there is nothing useful.

If the transcript is empty or too sparse to summarize, say that plainly and list which files you found.

## After the summary

Stay available for follow-up questions in this Claude Code session. When the user asks a question, answer from the transcript files first. Cite speaker names and timestamps when useful. If the user asks for a different format, transform the same transcript-backed facts rather than inventing missing context.
PROMPT
} > "${PROMPT_FILE}"

cat > "${LAUNCHER_FILE}" <<'SCRIPT'
#!/bin/zsh -li
printf '\e]0;Tuple Claude Summary\a'
clear
echo 'Starting Claude transcript summary...'
echo

SCRIPT_DIR="${0:A:h}"
PID_FILE="${SCRIPT_DIR}/claude-summary.pid"
PROMPT_FILE="${SCRIPT_DIR}/claude-summary-prompt.md"

echo $$ > "${PID_FILE}"
cd "${SCRIPT_DIR}" || exit 1

if ! command -v claude >/dev/null 2>&1; then
    echo "Claude Code was not found on your interactive shell PATH."
    echo "Make sure 'claude' works in a new terminal, then run the trigger again."
    echo
    read '?Press return to close.'
    exit 127
fi
if ! command -v python3 >/dev/null 2>&1; then
    echo "The Tuple watcher needs python3 (install Xcode Command Line Tools: xcode-select --install)."
    echo
    read '?Press return to close.'
    exit 127
fi

exec claude --allowed-tools Read Bash --name "Tuple Claude Summary" -- "$(cat "${PROMPT_FILE}")"
SCRIPT

chmod 0755 "${LAUNCHER_FILE}"

# --- launch_in_terminal: open the .command launcher in the user's terminal ---
# Uses LaunchServices (`open`) only — no direct binary exec and no AppleScript,
# so it triggers no macOS accessibility prompt and no stray empty windows.
# With PREFERRED_TERM empty, the launcher opens in your default handler for
# .command files (change it in Finder: right-click a .command > Open With >
# your terminal > Change All). Set PREFERRED_TERM to force one for this trigger.
# Ghostty, iTerm, and Terminal run an opened .command directly; Alacritty has no
# document handler, so it is launched with `open -na ... --args -e`.
launch_in_terminal() {
    local file="$1"
    case "${PREFERRED_TERM:-}" in
    "") open "$file" ;;
    ghostty) open -a "Ghostty" "$file" 2>/dev/null || open "$file" ;;
    iterm) open -a "iTerm" "$file" 2>/dev/null || open "$file" ;;
    terminal) open -a "Terminal" "$file" 2>/dev/null || open "$file" ;;
    alacritty) open -na "Alacritty" --args -e "$file" 2>/dev/null || open "$file" ;;
    *) echo "launch_in_terminal: unknown PREFERRED_TERM='${PREFERRED_TERM}'; using default handler" >&2; open "$file" ;;
    esac
}

if [ "${CLAUDE_TRANSCRIPT_SUMMARY_DRY_RUN:-}" = "1" ]; then
    echo "claude-transcript-summary: dry run generated ${LAUNCHER_FILE}"
    exit 0
fi

launch_in_terminal "${LAUNCHER_FILE}"
