#!/usr/bin/env bash
set -o nounset -o pipefail -o errexit
# VoiceMode Connect: Stop hook for agent wake-up
# Blocks agent from stopping when there are pending inbox messages.
#
# IMPORTANT: Must check stop_hook_active to prevent infinite loops.
# When stop_hook_active=true, a previous stop hook already blocked —
# allow the stop to prevent the agent from being stuck.

# Source voicemode config
if [ -f "$HOME/.voicemode/voicemode.env" ]; then
  set -a
  source "$HOME/.voicemode/voicemode.env"
  set +a
fi

# Exit early if Connect is not enabled (allow stop)
if [ "${VOICEMODE_CONNECT_ENABLED:-false}" != "true" ]; then
  exit 0
fi

# Exit early if jq is not available (can't parse hook input without it)
if ! command -v jq &>/dev/null; then
  exit 0
fi

# Debug logging (only when VOICEMODE_DEBUG is enabled)
if [ "${VOICEMODE_DEBUG:-false}" = "true" ]; then
  DEBUG_LOG="$HOME/.voicemode/logs/connect-hook-debug.log"
  mkdir -p "$(dirname "$DEBUG_LOG")"
else
  DEBUG_LOG="/dev/null"
fi

# Read hook input from stdin
INPUT=$(cat)

SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // empty' 2>/dev/null)
STOP_HOOK_ACTIVE=$(echo "$INPUT" | jq -r '.stop_hook_active // "false"' 2>/dev/null)

# CRITICAL: If stop_hook_active is true, a previous stop hook already blocked.
# We MUST allow the stop to prevent infinite loops.
if [ "$STOP_HOOK_ACTIVE" = "true" ]; then
  echo "stop_hook_active=true, allowing stop to prevent loop" >> "$DEBUG_LOG"
  exit 0
fi

if [ -z "$SESSION_ID" ]; then
  echo "No session_id, allowing stop" >> "$DEBUG_LOG"
  exit 0
fi

# Resolve agent name from session identity file
SESSIONS_DIR="$HOME/.voicemode/sessions"
SESSION_FILE="$SESSIONS_DIR/${SESSION_ID}.json"
AGENT_NAME=""

if [ -f "$SESSION_FILE" ]; then
  AGENT_NAME=$(jq -r '.agent_name // empty' "$SESSION_FILE" 2>/dev/null)
fi

# Fallback to VOICEMODE_AGENT_NAME env var
if [ -z "$AGENT_NAME" ]; then
  AGENT_NAME="${VOICEMODE_AGENT_NAME:-}"
fi

if [ -z "$AGENT_NAME" ]; then
  echo "No agent name for session $SESSION_ID, allowing stop" >> "$DEBUG_LOG"
  exit 0
fi

# Sanitize agent name
if [[ ! "$AGENT_NAME" =~ ^[a-zA-Z0-9._-]+$ ]]; then
  echo "Invalid agent name '$AGENT_NAME', allowing stop" >> "$DEBUG_LOG"
  exit 0
fi

echo "=== stop-notifications.sh $(date) session=$SESSION_ID agent=$AGENT_NAME ===" >> "$DEBUG_LOG"

# Check inbox for undelivered messages
INBOX_FILE="$HOME/.voicemode/connect/users/$AGENT_NAME/inbox"
DELIVERED_FILE="$HOME/.voicemode/connect/users/$AGENT_NAME/inbox.delivered"

if [ ! -f "$INBOX_FILE" ]; then
  echo "No inbox file, allowing stop" >> "$DEBUG_LOG"
  exit 0
fi

# Get the last delivered message ID
LAST_DELIVERED_ID=""
if [ -f "$DELIVERED_FILE" ]; then
  LAST_DELIVERED_ID=$(cat "$DELIVERED_FILE")
fi

# Read new messages from inbox (JSONL format)
MESSAGES=""
FOUND_LAST=false
if [ -z "$LAST_DELIVERED_ID" ]; then
  FOUND_LAST=true
fi

LATEST_ID=""
while IFS= read -r line; do
  [ -z "$line" ] && continue

  MSG_ID=$(echo "$line" | jq -r '.id // empty' 2>/dev/null)
  MSG_TYPE=$(echo "$line" | jq -r '.type // empty' 2>/dev/null)

  # Skip delivery confirmations
  [ "$MSG_TYPE" = "delivery_confirmation" ] && continue

  # Skip until we find the last delivered message
  if [ "$FOUND_LAST" = "false" ]; then
    if [ "$MSG_ID" = "$LAST_DELIVERED_ID" ]; then
      FOUND_LAST=true
    fi
    continue
  fi

  # Collect new message
  FROM=$(echo "$line" | jq -r '.from // "unknown"' 2>/dev/null)
  TEXT=$(echo "$line" | jq -r '.text // ""' 2>/dev/null)

  if [ -n "$TEXT" ]; then
    if [ -n "$MESSAGES" ]; then
      MESSAGES="${MESSAGES}\n---\n"
    fi
    MESSAGES="${MESSAGES}From ${FROM}: ${TEXT}"
    LATEST_ID="$MSG_ID"
  fi
done < "$INBOX_FILE"

if [ -z "$MESSAGES" ]; then
  echo "No pending messages, allowing stop" >> "$DEBUG_LOG"
  exit 0
fi

echo "Blocking stop: pending messages found, latest_id=$LATEST_ID" >> "$DEBUG_LOG"

# Mark messages as delivered (the agent will see them in the block reason)
if [ -n "$LATEST_ID" ]; then
  echo "$LATEST_ID" > "$DELIVERED_FILE"
fi

# Escape the messages for JSON output
ESCAPED_MESSAGES=$(printf '%s' "$MESSAGES" | sed 's/\\/\\\\/g; s/"/\\"/g' | tr '\n' ' ')

# Block the stop and deliver messages
cat <<HOOKEOF
{"decision": "block", "reason": "You have pending VoiceMode Connect messages:\n${ESCAPED_MESSAGES}"}
HOOKEOF

exit 0
