#!/bin/bash
set -euo pipefail

# Patchcord subscribe for Kimi CLI — background polling task.
# Kimi has no native push/WebSocket listener, so we poll the inbox
# and exit when messages arrive. Exiting triggers Kimi's auto-run
# (if the session is armed), waking the agent to read and reply.
#
# Usage: patchcord subscribe        (starts with default 30s interval)
#        patchcord subscribe 10     (starts with 10s interval)
#
# Resolves per-project .kimi-code/mcp.json only (walks up from cwd).
# No global fallback.

command -v jq >/dev/null 2>&1 || { echo "jq required" >&2; exit 1; }

# Resolve MCP config: PROJECT-scoped ONLY (walk up from cwd for .kimi-code/mcp.json).
# Kimi Code (the current product) uses .kimi-code/ — the legacy .kimi/ path is
# deprecated and MUST NOT be used; it also mismatched where `patchcord provision`
# writes the config (.kimi-code/mcp.json), so the listener never found it.
# NO global fallback: auto-launched by the (global) SessionStart hook on EVERY
# Kimi session, so a global fallback would start a listener for some leftover
# identity in every folder. No project config in the cwd tree => no patchcord
# agent here => exit quietly (0, not 1: must not spam stderr in non-patchcord dirs).
KIMI_MCP=""
dir="$PWD"
while [ "$dir" != "/" ]; do
  if [ -f "$dir/.kimi-code/mcp.json" ]; then
    KIMI_MCP="$dir/.kimi-code/mcp.json"
    break
  fi
  dir=$(dirname "$dir")
done

if [ -z "$KIMI_MCP" ] || [ ! -f "$KIMI_MCP" ]; then
  exit 0
fi

TOKEN=$(jq -r '.mcpServers.patchcord.headers.Authorization // empty' "$KIMI_MCP" 2>/dev/null | sed 's/^Bearer //i' || true)
URL=$(jq -r '.mcpServers.patchcord.url // empty' "$KIMI_MCP" 2>/dev/null || true)

if [ -z "$URL" ] || [ -z "$TOKEN" ]; then
  echo "Patchcord not configured in $KIMI_MCP" >&2
  exit 1
fi

BASE_URL=$(echo "$URL" | sed 's|/mcp$||; s|/mcp/bearer$||')

# Derive agent identity for pidfile
IDENTITY_RESP=$(curl -s --max-time 5 \
  -H "Authorization: Bearer ${TOKEN}" \
  "${BASE_URL}/api/inbox?limit=0" 2>/dev/null || echo "{}")
NAMESPACE_ID=$(echo "$IDENTITY_RESP" | jq -r '.namespace_id // empty' 2>/dev/null || true)
AGENT_ID=$(echo "$IDENTITY_RESP" | jq -r '.agent_id // empty' 2>/dev/null || true)

if [ -z "$NAMESPACE_ID" ] || [ -z "$AGENT_ID" ]; then
  echo "Could not determine agent identity — check your token" >&2
  exit 1
fi

PIDFILE="/tmp/patchcord_subscribe_${NAMESPACE_ID}_${AGENT_ID}.pid"
NOTIFY_FILE="${HOME}/.kimi/patchcord-subscribe-notify.txt"

# Always replace any existing listener for this project. Otherwise the agent
# sees an instant exit ("already running") and narrates it as "listener failed
# to start" / "exited cleanly because no messages" — confusing UX. By killing
# the old one, the new task stays in "running" state in Kimi's task browser,
# which is what the user expects when they invoke /flow:patchcord:subscribe.
if [ -f "$PIDFILE" ]; then
  OLD_PID=$(cat "$PIDFILE" 2>/dev/null || echo "")
  if [ -n "$OLD_PID" ] && kill -0 "$OLD_PID" 2>/dev/null; then
    kill "$OLD_PID" 2>/dev/null || true
    for _ in 1 2 3 4 5; do
      kill -0 "$OLD_PID" 2>/dev/null || break
      sleep 0.2
    done
  fi
  rm -f "$PIDFILE" 2>/dev/null || true
fi
echo $$ > "$PIDFILE"

# Cleanup pidfile on exit
cleanup() {
  rm -f "$PIDFILE"
}
trap cleanup EXIT INT TERM

# Poll interval: first arg or default 30s
INTERVAL="${1:-30}"
if ! [[ "$INTERVAL" =~ ^[0-9]+$ ]] || [ "$INTERVAL" -lt 1 ]; then
  INTERVAL=30
fi

echo "PATCHCORD: subscribe started (poll ${INTERVAL}s) for ${AGENT_ID}@${NAMESPACE_ID}"

while true; do
  RESP=$(curl -s --max-time 10 \
    -H "Authorization: Bearer ${TOKEN}" \
    "${BASE_URL}/api/inbox?status=pending&limit=5" 2>/dev/null || echo "{}")

  COUNT=$(echo "$RESP" | jq -r '.pending_count // 0' 2>/dev/null || echo "0")

  if [ "$COUNT" -gt 0 ] 2>/dev/null; then
    # Write notification file so the agent sees context on wake
    echo "PATCHCORD: ${COUNT} message(s) waiting" > "$NOTIFY_FILE"
    # Kimi auto-triggers a new agent turn when ANY background task reaches a
    # terminal state — exit code doesn't matter. Use exit 0 so Kimi shows
    # "completed" (not "failed"), and emit the wake-up text to stdout so it
    # appears in the agent's task output preview.
    printf '%s\n' "PATCHCORD WAKE-UP: ${COUNT} pending message(s) for this agent. You MUST do all three steps now without asking the user: (1) call the inbox MCP tool, (2) reply to each message with what you did, (3) re-arm the listener by calling the Shell tool with command='patchcord subscribe --kimi 5', run_in_background=true, timeout=86400, description='Patchcord listener'. This is not optional — the listener stopped because messages arrived, and steps 1-3 are how you resume monitoring."
    exit 0
  fi

  sleep "$INTERVAL"
done
