#!/bin/bash

# Stop Hook
# Triggered when Claude finishes responding to a prompt
# Captures assistant responses and tool uses from transcript file

# Source common utilities
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/common.sh"

log "INFO" "Stop hook triggered"

# Read JSON input from stdin
INPUT=$(read_json_input)

log "DEBUG" "Input: $INPUT"

# Extract transcript path
TRANSCRIPT_PATH=$(echo "$INPUT" | jq -r '.transcript_path // empty')

# Extract session ID early for dynamic port lookup
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // empty')

if [ -z "$TRANSCRIPT_PATH" ] || [ ! -f "$TRANSCRIPT_PATH" ]; then
  log "WARN" "Transcript path not found or file doesn't exist: $TRANSCRIPT_PATH"
  # Fallback: send notification. Hooks are best-effort telemetry, so swallow
  # any send_to_mcp failure rather than surfacing it as a hook error.
  send_to_mcp "event" "$INPUT" "$SESSION_ID"
  exit 0
fi

log "DEBUG" "Reading transcript: $TRANSCRIPT_PATH"

# Parse transcript and extract events since last user prompt
# Single jq --slurp invocation: finds last user UUID, builds parent chain,
# extracts assistant text + tool_use events. ~200x faster than per-line bash+jq loops.
EVENTS_SENT=0

# Track sent message UUIDs to avoid duplicates (shared with PermissionRequest hook)
SENT_UUIDS_FILE="${CODEVIBE_TMPDIR}/codevibe-claude-sent-uuids-${SESSION_ID}.txt"

# Load already-sent UUIDs for filtering
SENT_UUIDS_CONTENT=""
if [ -f "$SENT_UUIDS_FILE" ]; then
  SENT_UUIDS_CONTENT=$(cat "$SENT_UUIDS_FILE")
fi

# Find the index of the most recent REAL user prompt, then emit assistant
# text + tool_use events from all subsequent messages in file order.
#
# Previous implementation used a UUID-parent chain starting from the "last
# user message" — but tool_result messages ALSO have type "user", so the
# chain start was usually the last tool_result, missing every assistant
# message earlier in the same turn. Bug #39 (fixed 2026-04-14).
#
# A real user prompt has at least one content block of type "text". Tool_result
# user messages have content blocks of type "tool_result". We find the index
# of the last real user prompt and walk forward from there in file order.
#
# Output format: tab-separated lines: uuid\ttype\tcontent
# type is "text" for base64-encoded assistant text, "tool_use" for JSON tool uses
# Text is base64-encoded because it may contain newlines which break line-by-line read
TRANSCRIPT_EVENTS=$(jq -r --slurp --arg sent "$SENT_UUIDS_CONTENT" '
  # Index of the last "real" user prompt. A real prompt has .message.content
  # that is EITHER a string (simple text prompt) OR an array containing at
  # least one content block of type "text" (mixed content). Tool_result user
  # messages have an array of content blocks where every block is type
  # "tool_result" — those are NOT real prompts and must be excluded.
  (
    [ range(0; length) as $i
      | select(.[$i].type == "user" and (
          (.[$i].message.content | type) == "string" or
          ((.[$i].message.content | type) == "array" and
           (.[$i].message.content | any(.type? == "text")))
        ))
      | $i
    ]
    | last // -1
  ) as $startIdx |
  if $startIdx < 0 then empty
  else
    # Parse sent UUIDs
    ($sent | split("\n") | map(select(. != ""))) as $sentList |
    # Take messages after the real user prompt
    .[($startIdx + 1):] |
    .[] |
    select(.type == "assistant") |
    . as $msg |
    # Emit text content (base64-encoded to preserve newlines)
    (
      ($msg.uuid) as $uuid |
      ($sentList | any(. == $uuid)) as $alreadySent |
      if $alreadySent then
        "\($uuid)\talready_sent\t"
      else
        ([$msg.message.content[]? | select(.type == "text") | .text // empty] | join("\n\n")) as $text |
        if ($text | length) > 0 then
          "\($uuid)\ttext\t\($text | @base64)"
        else empty end
      end
    ),
    # Emit tool_use content as JSON (tojson escapes newlines, safe for line read)
    (
      $msg.message.content[]? | select(.type == "tool_use") |
      "\($msg.uuid)\ttool_use\t\(. | tojson | @base64)"
    )
  end
' "$TRANSCRIPT_PATH" 2>/dev/null)

log "DEBUG" "Transcript parsing complete"

if [ -n "$TRANSCRIPT_EVENTS" ]; then
  while IFS=$'\t' read -r MSG_UUID MSG_TYPE MSG_CONTENT; do
    if [ -z "$MSG_UUID" ]; then
      continue
    fi

    if [ "$MSG_TYPE" = "already_sent" ]; then
      log "DEBUG" "Skipping already sent message UUID: $MSG_UUID"
      EVENTS_SENT=$((EVENTS_SENT + 1))  # Count as sent to prevent fallback duplicate
      continue
    fi

    if [ "$MSG_TYPE" = "text" ] && [ -n "$MSG_CONTENT" ]; then
      # Decode base64-encoded text content
      DECODED_CONTENT=$(echo "$MSG_CONTENT" | base64 -d 2>/dev/null || echo "$MSG_CONTENT")

      EVENT_PAYLOAD=$(jq -n \
        --arg session_id "$SESSION_ID" \
        --arg content "$DECODED_CONTENT" \
        --arg hook_event_name "Stop" \
        --arg type "ASSISTANT_RESPONSE" \
        '{
          session_id: $session_id,
          hook_event_name: $hook_event_name,
          type: $type,
          content: $content
        }')

      log "DEBUG" "Sending assistant response: ${DECODED_CONTENT:0:100}..."

      send_to_mcp "event" "$EVENT_PAYLOAD" "$SESSION_ID"

      if [ $? -eq 0 ]; then
        EVENTS_SENT=$((EVENTS_SENT + 1))
        log "INFO" "Assistant response sent successfully"
        echo "$MSG_UUID" >> "$SENT_UUIDS_FILE"
      else
        log "ERROR" "Failed to send assistant response"
      fi
    fi

    if [ "$MSG_TYPE" = "tool_use" ] && [ -n "$MSG_CONTENT" ]; then
      # Decode base64-encoded tool_use JSON
      DECODED_TOOL=$(echo "$MSG_CONTENT" | base64 -d 2>/dev/null || echo "$MSG_CONTENT")
      TOOL_NAME=$(echo "$DECODED_TOOL" | jq -r '.name // empty')
      TOOL_INPUT=$(echo "$DECODED_TOOL" | jq -c '.input // {}')

      if [ -n "$TOOL_NAME" ]; then
        # Check if this is an interactive prompt (AskUserQuestion)
        if [ "$TOOL_NAME" = "AskUserQuestion" ]; then
          QUESTION_TEXT=$(echo "$TOOL_INPUT" | jq -r '.questions[0].question // empty')

          if [ -n "$QUESTION_TEXT" ]; then
            INTERACTIVE_PROMPT_PAYLOAD=$(jq -n \
              --arg session_id "$SESSION_ID" \
              --arg hook_event_name "Stop" \
              --arg type "INTERACTIVE_PROMPT" \
              --arg content "$QUESTION_TEXT" \
              --argjson tool_input "$TOOL_INPUT" \
              '{
                session_id: $session_id,
                hook_event_name: $hook_event_name,
                type: $type,
                content: $content,
                metadata: {
                  tool_name: "AskUserQuestion",
                  tool_input: $tool_input
                }
              }')

            log "DEBUG" "Sending interactive prompt: ${QUESTION_TEXT:0:100}..."

            send_to_mcp "event" "$INTERACTIVE_PROMPT_PAYLOAD" "$SESSION_ID"

            if [ $? -eq 0 ]; then
              EVENTS_SENT=$((EVENTS_SENT + 1))
              log "INFO" "Interactive prompt event sent successfully"
            else
              log "ERROR" "Failed to send interactive prompt event"
            fi
          fi
        fi

        # Send regular TOOL_USE event for all tools
        TOOL_EVENT_PAYLOAD=$(jq -n \
          --arg session_id "$SESSION_ID" \
          --arg hook_event_name "Stop" \
          --arg type "TOOL_USE" \
          --arg tool_name "$TOOL_NAME" \
          --argjson tool_input "$TOOL_INPUT" \
          '{
            session_id: $session_id,
            hook_event_name: $hook_event_name,
            type: $type,
            content: "{\"tool_name\":\"\($tool_name)\",\"tool_input\":\($tool_input)}",
            metadata: {
              tool_name: $tool_name
            }
          }')

        log "DEBUG" "Sending tool use: $TOOL_NAME"

        send_to_mcp "event" "$TOOL_EVENT_PAYLOAD" "$SESSION_ID"

        if [ $? -eq 0 ]; then
          EVENTS_SENT=$((EVENTS_SENT + 1))
          log "INFO" "Tool use event sent successfully: $TOOL_NAME"
        else
          log "ERROR" "Failed to send tool use event"
        fi
      fi
    fi

  done <<< "$TRANSCRIPT_EVENTS"
fi

# Fallback: if no events were extracted from transcript but last_assistant_message is available,
# send it directly. This handles the race condition where the Stop hook fires before the
# assistant response is fully written to the transcript file.
if [ "$EVENTS_SENT" -eq 0 ]; then
  LAST_ASSISTANT_MSG=$(echo "$INPUT" | jq -r '.last_assistant_message // empty')
  if [ -n "$LAST_ASSISTANT_MSG" ] && [ "$LAST_ASSISTANT_MSG" != "null" ]; then
    log "INFO" "No events from transcript, using last_assistant_message fallback"
    FALLBACK_PAYLOAD=$(jq -n \
      --arg session_id "$SESSION_ID" \
      --arg content "$LAST_ASSISTANT_MSG" \
      --arg hook_event_name "Stop" \
      --arg type "ASSISTANT_RESPONSE" \
      '{
        session_id: $session_id,
        hook_event_name: $hook_event_name,
        type: $type,
        content: $content
      }')

    send_to_mcp "event" "$FALLBACK_PAYLOAD" "$SESSION_ID"

    if [ $? -eq 0 ]; then
      EVENTS_SENT=$((EVENTS_SENT + 1))
      log "INFO" "Assistant response sent via fallback"
    else
      log "ERROR" "Failed to send fallback assistant response"
    fi
  fi
fi

log "INFO" "Stop hook completed. Events sent: $EVENTS_SENT"

# Clean up sent UUIDs file after Stop hook completes (turn is finished)
if [ -f "$SENT_UUIDS_FILE" ]; then
  rm -f "$SENT_UUIDS_FILE"
  log "DEBUG" "Cleaned up sent UUIDs file"
fi

exit 0
