#!/bin/sh
# Cirvix AgentControl installer.
#
#   curl -fsSL https://www.cirvix.com/install.sh | sh
#
# You are about to pipe a script from the internet into a shell, on the advice
# of a company selling you a security product. Read it first:
#
#   curl -fsSL https://www.cirvix.com/install.sh -o install.sh
#   less install.sh && sh install.sh
#
# Homebrew alternative (macOS & Linux):
#   brew tap cirvix/tap && brew install cirvix
#
# This script installs the compiled standalone Cirvix binary daemon (Go/Rust),
# with zero runtime dependencies. If preferred, Node.js / npm distribution
# is also supported:
#   npm install -g @cirvix_ai/agent-control

set -eu

VERSION="0.1.5"
PKG="@cirvix_ai/agent-control"
BIN_NAME="cirvix"
DRY=0
FORCE_NPM=0
INSTALL_DIR=""

for arg in "$@"; do
  case "$arg" in
    --dry-run) DRY=1 ;;
    --npm) FORCE_NPM=1 ;;
    --dir=*) INSTALL_DIR="${arg#*=}" ;;
    -h|--help)
      echo "usage: install.sh [--dry-run] [--npm] [--dir=/path/to/bin]"
      echo "  Default: installs standalone compiled binary (Go/Rust)"
      echo "  --npm:   installs @cirvix_ai/agent-control via npm"
      exit 0 ;;
    *) echo "install.sh: unknown option '$arg'" >&2; exit 2 ;;
  esac
done

say()  { printf '  %s\n' "$1"; }
fail() { printf '\n  %s\n\n' "$1" >&2; exit 1; }

printf '\n  cirvix · enterprise agent control plane installer (%s)\n\n' "$VERSION"

# --- refuse root -----------------------------------------------------------
if [ "$(id -u 2>/dev/null || echo 1)" = "0" ] && [ "${CIRVIX_ALLOW_ROOT:-}" != "1" ]; then
  fail "Refusing to install as root. Re-run as your normal user, or set CIRVIX_ALLOW_ROOT=1 if you mean it."
fi

# --- Determine install target directory -------------------------------------
if [ -z "$INSTALL_DIR" ]; then
  if [ -d "$HOME/.local/bin" ] && [ -w "$HOME/.local/bin" ]; then
    INSTALL_DIR="$HOME/.local/bin"
  elif [ -w "/usr/local/bin" ]; then
    INSTALL_DIR="/usr/local/bin"
  else
    INSTALL_DIR="$HOME/.local/bin"
    mkdir -p "$INSTALL_DIR"
  fi
fi

# --- Architecture & OS detection -------------------------------------------
OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
ARCH="$(uname -m)"

case "$ARCH" in
  x86_64|amd64) TARGET_ARCH="amd64" ;;
  arm64|aarch64) TARGET_ARCH="arm64" ;;
  *) TARGET_ARCH="unknown" ;;
esac

say "os          $OS"
say "arch        $TARGET_ARCH"
say "install_dir $INSTALL_DIR"
say ""

# --- If standalone binary supported and not forced npm ----------------------
if [ "$FORCE_NPM" = "0" ] && [ "$TARGET_ARCH" != "unknown" ]; then
  case "$OS" in
    linux|darwin)
      BINARY_URL="https://github.com/CIRVIX/agent-control/releases/download/v${VERSION}/cirvix-${OS}-${TARGET_ARCH}"
      say "target      standalone single-binary daemon ($OS-$TARGET_ARCH)"
      
      if [ "$DRY" = "1" ]; then
        say "dry run — would download $BINARY_URL -> $INSTALL_DIR/$BIN_NAME"
        printf '\n'
        exit 0
      fi

      TMP_FILE="$(mktemp -t cirvix.XXXXXX)"
      say "fetching    $BINARY_URL"
      if curl -fsSL --connect-timeout 10 "$BINARY_URL" -o "$TMP_FILE" 2>/dev/null; then
        chmod +x "$TMP_FILE"
        mv "$TMP_FILE" "$INSTALL_DIR/$BIN_NAME"
        say "installed   $INSTALL_DIR/$BIN_NAME"
        
        # Verify PATH
        case ":${PATH}:" in
          *:"$INSTALL_DIR":*) ;;
          *)
            say ""
            say "NOTE: $INSTALL_DIR is not in your PATH."
            say "Add it to your shell configuration (.bashrc / .zshrc):"
            say "  export PATH=\"\$PATH:$INSTALL_DIR\""
            ;;
        esac

        cat <<'NEXT'

  Next, in order:

    cirvix daemon                                  start background UDS & eBPF policy socket
    cirvix scan                                    scan local system for unmonitored agents
    cirvix gateway                                 start stdio MCP gateway for Claude Code / Cursor

  Docs & Quickstart: https://www.cirvix.com/docs.html

NEXT
        exit 0
      else
        say "Binary download unavailable; falling back to package manager install..."
      fi
      ;;
  esac
fi

# --- Node / npm Fallback ----------------------------------------------------
say "checking    node & npm runtime fallback..."
MIN_NODE=20

if ! command -v node >/dev/null 2>&1; then
  fail "Node is not on your PATH. Either install Node ${MIN_NODE}+ or download the standalone binary: https://www.cirvix.com/docs.html#install"
fi

NODE_RAW="$(node --version)"
NODE_MAJOR="$(printf '%s' "$NODE_RAW" | sed 's/^v//' | cut -d. -f1)"

if [ "$NODE_MAJOR" -lt "$MIN_NODE" ]; then
  fail "Node ${NODE_RAW} is too old. Cirvix needs Node ${MIN_NODE} or later."
fi

if ! command -v npm >/dev/null 2>&1; then
  fail "npm is not on your PATH. Install with your package manager: npm install -g $PKG"
fi

if [ "$DRY" = "1" ]; then
  say "dry run — would execute: npm install -g $PKG"
  printf '\n'
  exit 0
fi

if ! npm install -g "$PKG"; then
  say "Global npm install failed. Try: npx $PKG scan"
  exit 1
fi

say "installed   $(npm list -g $PKG --depth=0 2>/dev/null || echo "$PKG")"

cat <<'NEXT'

  Next, in order:

    cirvix scan                                    what on this machine is ungoverned
    cirvix check --action fs.read --resource .env  decide one call, see the reasoning
    cirvix init                                    detect your agents and write a policy

  Docs: https://www.cirvix.com/docs.html

NEXT
