#!/usr/bin/env sh
# perseus install.
#
# Two install methods, in preference order:
#   1. standalone binary  — a single PyInstaller-frozen executable, NO
#                           python/uv/pip on the target. Preferred when a binary
#                           for this OS/arch is published.
#   2. wheel (fallback)    — installs into an isolated uv tool venv. Needs uv +
#                           python>=3.12. The original, always-available path.
#
# The binary path removes the uv+python friction that bounced first-time users.
# We still fall back to the wheel automatically so this is purely additive — the
# live wheel install is never broken.
#
# The wheel is republished on every main deploy (infra/deploy/publish_wheel.sh);
# binaries are published per release by .github/workflows/binaries.yml. We
# resolve the wheel's real PEP 427 filename from <base>/latest.txt because uv
# rejects renamed wheels.
#
# Force a method / pin a build:
#   PERSEUS_INSTALL_METHOD=wheel   curl -fsSL …/install.sh | sh   # skip the binary
#   PERSEUS_INSTALL_METHOD=binary  curl -fsSL …/install.sh | sh   # binary or fail
#   PERSEUS_WHEEL_URL=https://perseus.computer/install/<sha>/perseus-0.1.0-py3-none-any.whl
#   PERSEUS_BINARY_URL=https://perseus.computer/install/bin/<sha>/perseus-linux-x86_64
set -eu

INSTALL_BASE="${PERSEUS_INSTALL_BASE:-https://perseus.computer/install}"
BIN_BASE="${PERSEUS_BINARY_BASE:-$INSTALL_BASE/bin}"
INSTALL_METHOD="${PERSEUS_INSTALL_METHOD:-auto}"

# Best-effort: drop the man page into the user manpath so `man perseus` works.
# Non-fatal — a failure here never breaks the install. Shared by both methods.
install_man_page() {
  MAN_SRC="$(perseus _man-path 2>/dev/null || true)"
  if [ -n "$MAN_SRC" ] && [ -f "$MAN_SRC" ]; then
    MAN_DIR="$HOME/.local/share/man/man1"
    if mkdir -p "$MAN_DIR" 2>/dev/null && cp "$MAN_SRC" "$MAN_DIR/perseus.1" 2>/dev/null; then
      echo "man page installed (try: man perseus)"
    fi
  fi
}

install_completion() {
  PERSEUS_BIN="$1"
  TMP_LOG="$(mktemp)"
  if "$PERSEUS_BIN" completion install --quiet >"$TMP_LOG" 2>&1; then
    echo "shell completion installed (restart your terminal to activate it)"
  else
    echo "shell completion was not installed automatically:" >&2
    sed 's/^/  /' "$TMP_LOG" >&2 || true
    echo "Run 'perseus completion install bash|zsh|fish' after install." >&2
  fi
  rm -f "$TMP_LOG"
}

print_next_steps() {
  cat <<'EOF'

Next steps:
  perseus login                  # authenticate to perseus.computer
  perseus index                  # index the current git repo
  perseus watch                  # keep active-work edits fresh in the background
  perseus query "..."            # run a retrieval query (a terse phrase beats a question)
  perseus rules add              # install the perseus code-search rules for your agents
  perseus update                 # pull the latest build + reinstall
EOF
}

# Resolve the published binary asset name for this OS/arch, or empty if we don't
# ship a binary for it (then we fall back to the wheel).
binary_asset() {
  os="$(uname -s)"
  arch="$(uname -m)"
  case "$os" in
    Darwin)
      case "$arch" in
        arm64 | aarch64) echo "perseus-macos-arm64" ;;
        x86_64) echo "perseus-macos-x86_64" ;;
        *) echo "" ;;
      esac
      ;;
    Linux)
      case "$arch" in
        x86_64) echo "perseus-linux-x86_64" ;;
        *) echo "" ;; # no linux-arm64 binary yet — wheel covers it
      esac
      ;;
    *) echo "" ;; # Windows uses install.ps1
  esac
}

# Try to install the standalone binary. Returns 0 on success, 1 to fall back.
install_binary() {
  asset="$(binary_asset)"
  if [ -n "${PERSEUS_BINARY_URL:-}" ]; then
    url="$PERSEUS_BINARY_URL"
  elif [ -n "$asset" ]; then
    url="$BIN_BASE/$asset"
  else
    return 1
  fi

  bindir="$HOME/.local/bin"
  mkdir -p "$bindir"
  tmp="$(mktemp)"
  echo "Fetching perseus binary from $url ..."
  if ! curl -fsSL "$url" -o "$tmp"; then
    rm -f "$tmp"
    return 1
  fi
  chmod +x "$tmp"
  mv "$tmp" "$bindir/perseus"
  # pctl is the same frozen binary under a different name (argv[0] dispatch);
  # fetch it best-effort so the ops CLI is present too.
  pctl_asset="$(echo "$asset" | sed 's/^perseus-/pctl-/')"
  if [ -n "$pctl_asset" ] && curl -fsSL "$BIN_BASE/$pctl_asset" -o "$bindir/pctl" 2>/dev/null; then
    chmod +x "$bindir/pctl"
  fi

  case ":$PATH:" in
    *":$bindir:"*) ;;
    *) echo "Note: add $bindir to your PATH (e.g. export PATH=\"$bindir:\$PATH\")." ;;
  esac

  echo ""
  if "$bindir/perseus" --version >/dev/null 2>&1; then
    printf 'perseus installed: '
    "$bindir/perseus" --version
  else
    echo "perseus binary installed to $bindir (ensure it's on PATH, then run 'perseus --version')."
  fi
  install_man_page
  install_completion "$bindir/perseus"
  print_next_steps
  return 0
}

# The wheel install (fallback): uv + python>=3.12, into an isolated tool venv.
install_wheel() {
# 1. uv — installs the wheel into an isolated tool venv.
if ! command -v uv >/dev/null 2>&1; then
  echo "Installing uv..."
  curl -LsSf https://astral.sh/uv/install.sh | sh
  if [ -d "$HOME/.local/bin" ]; then
    PATH="$HOME/.local/bin:$PATH"
  fi
fi
if ! command -v uv >/dev/null 2>&1; then
  echo "uv was not found after install. Add ~/.local/bin to PATH, then rerun." >&2
  exit 1
fi

# 2. Resolve the wheel URL. PERSEUS_WHEEL_URL pins an exact build; otherwise
#    latest.txt names the current wheel (a real PEP 427 filename uv accepts).
if [ -n "${PERSEUS_WHEEL_URL:-}" ]; then
  WHEEL_URL="$PERSEUS_WHEEL_URL"
else
  WHEEL_NAME="$(curl -fsSL "$INSTALL_BASE/latest.txt" 2>/dev/null | tr -d '[:space:]')"
  if [ -z "$WHEEL_NAME" ]; then
    cat >&2 <<EOF
Could not resolve the latest perseus wheel from $INSTALL_BASE/latest.txt.

If perseus.computer is reachable, a deploy may not have published yet. Retry
shortly, or pin a known build:
  PERSEUS_WHEEL_URL=https://perseus.computer/install/<sha>/perseus-0.1.63-py3-none-any.whl \\
    curl -fsSL https://perseus.computer/install.sh | sh
EOF
    exit 1
  fi
  # latest.txt must name a bare wheel filename — reject a path separator (no
  # traversal out of /install/) or a non-.whl extension.
  case "$WHEEL_NAME" in
    */*) echo "latest.txt names a path, not a wheel filename: $WHEEL_NAME" >&2; exit 1 ;;
  esac
  case "$WHEEL_NAME" in
    *.whl) ;;
    *) echo "latest.txt does not name a .whl: $WHEEL_NAME" >&2; exit 1 ;;
  esac
  WHEEL_URL="$INSTALL_BASE/$WHEEL_NAME"
fi
FNAME="$(basename "$WHEEL_URL")"

# 3. Fetch the wheel under its real name, then install.
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT
echo "Fetching perseus wheel from $WHEEL_URL ..."
if ! curl -fsSL "$WHEEL_URL" -o "$TMP_DIR/$FNAME"; then
  echo "Failed to fetch $WHEEL_URL. Try again shortly." >&2
  exit 1
fi
echo "Installing perseus CLI..."
uv tool install --force "$TMP_DIR/$FNAME"

echo ""
if command -v perseus >/dev/null 2>&1 && perseus --version >/dev/null 2>&1; then
  printf 'perseus installed: '
  perseus --version
else
  echo "perseus installed (run 'perseus --version' to confirm; ensure ~/.local/bin is on PATH)."
fi

install_man_page
if command -v perseus >/dev/null 2>&1; then
  install_completion "$(command -v perseus)"
else
  echo "shell completion was not installed automatically: perseus is not on PATH yet" >&2
  echo "Run 'perseus completion install bash|zsh|fish' after adding the uv tool bin dir to PATH." >&2
fi
print_next_steps
}

# --- dispatch: prefer the standalone binary, fall back to the wheel ---------
case "$INSTALL_METHOD" in
  wheel)
    install_wheel
    ;;
  binary)
    if ! install_binary; then
      echo "No standalone binary available for this OS/arch (set PERSEUS_INSTALL_METHOD=wheel to use the wheel)." >&2
      exit 1
    fi
    ;;
  auto | "")
    if ! install_binary; then
      echo "Standalone binary unavailable for this platform — falling back to the wheel install."
      install_wheel
    fi
    ;;
  *)
    echo "Unknown PERSEUS_INSTALL_METHOD='$INSTALL_METHOD' (expected: auto | binary | wheel)." >&2
    exit 1
    ;;
esac
