#!/usr/bin/env bash
# P2HS Cursor Agent - Wrapper for server-side Cursor Agent CLI code generation.
#
# Usage (named flags):
#   p2hs-cursor-agent.sh --dir <repo_path> --message "<prompt>" [--yes] [--rules <rules_file>]
#
# Environment:
#   CURSOR_CLI_PATH  - Full path to agent binary (auto-detected if not set)
#   CURSOR_API_KEY   - Cursor API key for authentication
#   CURSOR_TIMEOUT   - Timeout in seconds (default: 300)
#   CURSOR_OUTPUT_FORMAT - e.g. stream-json for live NDJSON (set by P2HS when enabled)
#   CURSOR_STREAM_PARTIAL_OUTPUT - 1 with stream-json for incremental assistant deltas
#   P2HS_CURSOR_AGENT_HOME - If set, persistent HOME for Cursor agent state (required for --resume across runs)
#   CURSOR_RESUME_SESSION_ID - Cursor agent chat/session id for ``agent --resume`` (set by P2HS when known)
#   P2HS_CURSOR_AGENT_NO_COREUTILS_TIMEOUT - If 1, run agent without GNU ``timeout`` (P2HS still enforces a
#     Python asyncio wall clock). Use if you see ``timeout: the monitored command dumped core`` or odd
#     exit codes when the agent binary itself is unstable.
#
# Exit codes: 0 = success, 1 = error, 124 = timeout

set -e

TIMEOUT="${CURSOR_TIMEOUT:-300}"
MODEL="${CURSOR_MODEL:-}"
REPO_PATH=""
PROMPT=""
RULES_FILE=""

# ── Locate agent binary ───────────────────────────────────────────────────────
_find_agent() {
  if [[ -n "${CURSOR_CLI_PATH:-}" && -x "$CURSOR_CLI_PATH" ]]; then
    echo "$CURSOR_CLI_PATH"
    return
  fi
  local candidates=(
    "$HOME/.local/bin/agent"
    "$HOME/.cursor/bin/agent"
    "$HOME/.local/bin/cursor"
    "$HOME/.cursor/bin/cursor"
    "/usr/local/bin/agent"
    "/usr/local/bin/cursor"
  )
  for c in "${candidates[@]}"; do
    [[ -x "$c" ]] && echo "$c" && return
  done
  command -v agent 2>/dev/null || command -v cursor 2>/dev/null || true
}

AGENT_BIN="$(_find_agent)"
if [[ -z "$AGENT_BIN" ]]; then
  echo "Error: cursor agent binary not found. Set CURSOR_CLI_PATH or add agent to PATH." >&2
  exit 1
fi

# ── Parse arguments ───────────────────────────────────────────────────────────
while [[ $# -gt 0 ]]; do
  case "$1" in
    --dir)      REPO_PATH="$2"; shift 2 ;;
    --message)  PROMPT="$2";    shift 2 ;;
    --rules)    RULES_FILE="$2"; shift 2 ;;
    --model)    MODEL="$2";     shift 2 ;;
    --yes)      shift ;;  # accepted for compat, --force is always passed
    *)          echo "Unknown flag: $1" >&2; exit 1 ;;
  esac
done

if [[ -z "$REPO_PATH" || -z "$PROMPT" ]]; then
  echo "Usage: p2hs-cursor-agent.sh --dir <repo_path> --message \"<prompt>\"" >&2
  exit 1
fi

if [[ ! -d "$REPO_PATH" ]]; then
  echo "Error: Repo path does not exist: $REPO_PATH" >&2
  exit 1
fi

# Resolve to absolute path
REPO_PATH="$(cd "$REPO_PATH" && pwd)"

# ── Write .cursorrules if provided ────────────────────────────────────────────
# .cursorrules in the workspace root is automatically read by the agent.
if [[ -n "$RULES_FILE" && -f "$RULES_FILE" ]]; then
  cp "$RULES_FILE" "$REPO_PATH/.cursorrules"
fi

# ── Sandbox / persistent agent home ───────────────────────────────────────────
# Default: ephemeral temp dir (no cross-run session). P2HS sets P2HS_CURSOR_AGENT_HOME so
# ``--resume`` can reuse the same Cursor CLI chat and local session index.
if [[ -n "${P2HS_CURSOR_AGENT_HOME:-}" ]]; then
  SANDBOX_DIR="$P2HS_CURSOR_AGENT_HOME"
  mkdir -p "$SANDBOX_DIR"
  trap - EXIT
else
  SANDBOX_DIR="$(mktemp -d /tmp/cursor-sandbox-XXXXXX)"
  trap 'rm -rf "$SANDBOX_DIR"' EXIT
fi

export HOME="$SANDBOX_DIR"
export XDG_CONFIG_HOME="$SANDBOX_DIR/.config"
export XDG_DATA_HOME="$SANDBOX_DIR/.local/share"
export XDG_CACHE_HOME="$SANDBOX_DIR/.cache"
export XDG_STATE_HOME="$SANDBOX_DIR/.local/state"
# Prevent git from resolving past the project root
export GIT_CEILING_DIRECTORIES="$(dirname "$REPO_PATH")"

# Pass API key if set in environment
if [[ -n "${CURSOR_API_KEY:-}" ]]; then
  export CURSOR_API_KEY
fi

cd "$REPO_PATH" || exit 1

# Do not print absolute server paths (exposed to WebSocket clients). Project id is basename only.
echo "[p2hs-cursor-agent] starting agent=$(basename "$AGENT_BIN") timeout=${TIMEOUT}s project=$(basename "$REPO_PATH")" >&2

# ── Run Cursor Agent ──────────────────────────────────────────────────────────
# --workspace  : restrict agent to this directory
# --print      : headless/non-interactive output (no TUI)
# --force      : allow all file/shell commands without prompting
# --trust      : trust workspace without interactive prompt (required with --print)
MODEL_FLAG=()
[[ -n "$MODEL" ]] && MODEL_FLAG=(--model "$MODEL")

OUTPUT_FORMAT="${CURSOR_OUTPUT_FORMAT:-text}"
STREAM_FLAGS=()
if [[ "$OUTPUT_FORMAT" != "text" && -n "$OUTPUT_FORMAT" ]]; then
  STREAM_FLAGS=(--output-format "$OUTPUT_FORMAT")
  if [[ "${CURSOR_STREAM_PARTIAL_OUTPUT:-}" == "1" ]]; then
    STREAM_FLAGS+=(--stream-partial-output)
  fi
fi

RESUME_FLAGS=()
if [[ -n "${CURSOR_RESUME_SESSION_ID:-}" ]]; then
  RESUME_FLAGS=(--resume "$CURSOR_RESUME_SESSION_ID")
fi

AGENT_CMD=(
  "$AGENT_BIN"
  --workspace "$REPO_PATH"
  --print
  --force
  --trust
  "${STREAM_FLAGS[@]}"
  "${MODEL_FLAG[@]}"
  "${RESUME_FLAGS[@]}"
  "$PROMPT"
)

if [[ "${P2HS_CURSOR_AGENT_NO_COREUTILS_TIMEOUT:-}" == "1" ]]; then
  exec "${AGENT_CMD[@]}" 2>&1
fi

exec timeout "$TIMEOUT" "${AGENT_CMD[@]}" 2>&1
