#!/usr/bin/env bash
#
# Builds the Integration-channel Oz CLI for Linux x86_64 (musl) and uploads it
# to the SSH integration testing VM so that remote-server integration tests run
# against the binary built from the current branch.
#
# This script is intended to be run once by CI before the integration test
# suite, not by individual test functions. The binary is placed at the
# versioned Integration channel path on the remote host, which is where the
# Integration channel's `check_binary` looks.
#
# Prerequisites (same as script/deploy_remote_server):
#   On Linux, install curl, sha256sum, tar, and sshpass.
#   rustup target add x86_64-unknown-linux-musl
#   gcloud CLI authenticated for the warp-ssh-integration-testing project
#
# Usage:
#   script/deploy_remote_server_to_test_vm

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WORKSPACE_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"

TARGET="x86_64-unknown-linux-musl"
CARGO_PROFILE="dev-remote"
FEATURES="crash_reporting,standalone,agent_mode_debug,remote_codebase_indexing"
WARP_BIN="integration"
# The integration test runner uses Channel::Integration, which maps to
# cli_command_name() = "oz-integration", remote_server_dir() = "~/.warp-dev/remote-server",
# and remote_server_binary() = "oz-integration-${pinned_version}".
# See crates/warp_core/src/channel/mod.rs, crates/remote_server/src/setup.rs,
# and crates/integration/src/bin/integration.rs.
#
# We intentionally build app/src/bin/integration.rs instead of the normal
# Local-channel app binary. The Local-channel release bundle requires
# warp-channel-config to generate local_config.json at compile time, but this CI
# path should not depend on private channel config. The Integration-channel
# binary embeds a static non-secret config instead.
REMOTE_DIR=".warp-dev/remote-server"

# Dedicated remote-server test VM, configured similarly to the SSH integration
# test VM but isolated from the general SSH integration suite.
REMOTE_USERS=(bash zsh)
REMOTE_HOST="ssh-remote-server-testing"
REMOTE_PORT="22"
PROXY_COMMAND="gcloud compute start-iap-tunnel ssh-remote-server-testing ${REMOTE_PORT} --listen-on-stdin --project=warp-ssh-integration-testing --zone=us-east4-b"


app_version() {
  if [[ -n "${GIT_RELEASE_TAG:-}" ]]; then
    echo "$GIT_RELEASE_TAG"
    return
  fi

  cargo metadata --no-deps --format-version 1 \
    | python3 -c 'import json, sys; print(next(p["version"] for p in json.load(sys.stdin)["packages"] if p["name"] == "remote_server" and p["manifest_path"].endswith("/crates/remote_server/Cargo.toml")))'
}

# ── Preflight checks ──────────────────────────────────────────────
source "$SCRIPT_DIR/linux/configure_musl_toolchain" "$TARGET"

if ! rustup target list --installed 2>/dev/null | grep -q "$TARGET"; then
  echo "Error: $TARGET target not installed." >&2
  echo "Install it with: rustup target add $TARGET" >&2
  exit 1
fi

BUNDLE_VERSION="$(app_version)"
BUNDLE_BINARY_NAME="oz-integration"
BINARY_NAME="$BUNDLE_BINARY_NAME-$BUNDLE_VERSION"

# ── Build ─────────────────────────────────────────────────────────

CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$WORKSPACE_ROOT/target}"
OUTPUT_DIR="$CARGO_TARGET_DIR/$TARGET/$CARGO_PROFILE"
BUILT_BINARY="$OUTPUT_DIR/$WARP_BIN"
LOCAL_BUNDLE_DIR="$OUTPUT_DIR/remote-server-integration-bundle"
LOCAL_BUNDLE_TARBALL="$OUTPUT_DIR/remote-server-integration-bundle.tar.gz"

echo "==> Building Integration-channel Oz CLI for $TARGET (profile=$CARGO_PROFILE)"

cargo build \
    -p warp \
    --bin "$WARP_BIN" \
    --target "$TARGET" \
    --profile "$CARGO_PROFILE" \
    --features "$FEATURES"

if [[ ! -f "$BUILT_BINARY" ]]; then
  echo "Error: Expected binary not found at $BUILT_BINARY" >&2
  exit 1
fi

BINARY_SIZE=$(du -h "$BUILT_BINARY" | cut -f1)
echo "==> Build complete ($BINARY_SIZE)"

rm -rf "$LOCAL_BUNDLE_DIR"
mkdir -p "$LOCAL_BUNDLE_DIR"
cp "$BUILT_BINARY" "$LOCAL_BUNDLE_DIR/$BUNDLE_BINARY_NAME"
"$WORKSPACE_ROOT/script/prepare_bundled_resources" \
  "$LOCAL_BUNDLE_DIR/resources" \
  integration \
  "$CARGO_PROFILE"
tar -czf "$LOCAL_BUNDLE_TARBALL" -C "$LOCAL_BUNDLE_DIR" .

# ── Upload via SCP through GCP IAP tunnel ─────────────────────────
# The test VM uses password auth (same as the SSH integration tests).
# sshpass provides the password non-interactively for SSH/SCP.
SSH_PASSWORD="password"
SSH_OPTS=(-p "$REMOTE_PORT" -o "ProxyCommand=$PROXY_COMMAND" -o PreferredAuthentications=password -o PubkeyAuthentication=no -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null)

if command -v sshpass &>/dev/null; then
  export SSHPASS="$SSH_PASSWORD"
  SSH_CMD=(sshpass -e ssh)
  SCP_CMD=(sshpass -e scp)
else
  echo "Warning: sshpass not found, SSH/SCP will prompt for password interactively." >&2
  if [[ "$(uname -s)" == "Darwin" ]]; then
    echo "Install it with: brew install hudochenkov/sshpass/sshpass" >&2
  elif [[ "$(uname -s)" == "Linux" ]]; then
    echo "Install it with: sudo apt-get install sshpass" >&2
  fi
  SSH_CMD=(ssh)
  SCP_CMD=(scp)
fi

for REMOTE_USER in "${REMOTE_USERS[@]}"; do
  echo "==> Ensuring remote directory exists for ${REMOTE_USER}"
  "${SSH_CMD[@]}" "${SSH_OPTS[@]}" "${REMOTE_USER}@${REMOTE_HOST}" "mkdir -p ~/$REMOTE_DIR"
  echo "==> Stopping stale remote server daemons for ${REMOTE_USER}"
  "${SSH_CMD[@]}" "${SSH_OPTS[@]}" "${REMOTE_USER}@${REMOTE_HOST}" "bash -s -- '$REMOTE_DIR'" <<'REMOTE_SCRIPT'
set -euo pipefail

REMOTE_ROOT="$HOME/$1"
mkdir -p "$REMOTE_ROOT"

shopt -s nullglob
for PID_FILE in "$REMOTE_ROOT"/*/server.pid; do
  DAEMON_DIR="$(dirname "$PID_FILE")"
  PID="$(cat "$PID_FILE" 2>/dev/null || true)"

  if [[ "$PID" =~ ^[0-9]+$ ]] && [[ -d "/proc/$PID" ]]; then
    CMDLINE="$(tr '\0' ' ' < "/proc/$PID/cmdline" 2>/dev/null || true)"
    if [[ "$CMDLINE" == *remote-server-daemon* ]]; then
      echo "Stopping stale remote-server daemon pid $PID"
      kill "$PID" 2>/dev/null || true

      for _ in {1..50}; do
        if ! kill -0 "$PID" 2>/dev/null; then
          break
        fi
        sleep 0.1
      done

      if kill -0 "$PID" 2>/dev/null; then
        echo "Force-stopping stale remote-server daemon pid $PID"
        kill -9 "$PID" 2>/dev/null || true
      fi
    fi
  fi

  rm -f "$DAEMON_DIR/server.sock" "$DAEMON_DIR/server.pid"
done

rm -f "$REMOTE_ROOT"/remote-server-integration-bundle-*.tar.gz
REMOTE_SCRIPT

  TMP_BUNDLE_NAME="remote-server-integration-bundle-${GITHUB_RUN_ID:-local}-$$-${REMOTE_USER}.tar.gz"
  echo "==> Uploading bundle to ${REMOTE_USER}@${REMOTE_HOST}:~/$REMOTE_DIR/$TMP_BUNDLE_NAME"
  "${SCP_CMD[@]}" -P "$REMOTE_PORT" \
    -o "ProxyCommand=$PROXY_COMMAND" \
    -o PreferredAuthentications=password \
    -o PubkeyAuthentication=no \
    -o StrictHostKeyChecking=no \
    -o UserKnownHostsFile=/dev/null \
    "$LOCAL_BUNDLE_TARBALL" \
    "${REMOTE_USER}@${REMOTE_HOST}:~/$REMOTE_DIR/$TMP_BUNDLE_NAME"

  echo "==> Installing binary and resources for ${REMOTE_USER}"
  # Args: <remote dir> <tarball name> <binary name in tarball> <installed name>.
  # The tarball ships the unversioned binary beside its resources/ tree; the
  # installed binary carries the version suffix the Integration channel
  # launches. The resources tree lands at `bundled_resources`, the global
  # version-independent location the daemon reads (must match
  # BUNDLED_RESOURCES_DIR_NAME in crates/remote_server/src/setup.rs).
  "${SSH_CMD[@]}" "${SSH_OPTS[@]}" "${REMOTE_USER}@${REMOTE_HOST}" \
    "bash -s -- '$REMOTE_DIR' '$TMP_BUNDLE_NAME' '$BUNDLE_BINARY_NAME' '$BINARY_NAME'" <<'REMOTE_SCRIPT'
set -euo pipefail

cd "$HOME/$1"
tar -xzf "$2"
rm -f "$2"

rm -rf bundled_resources
mv resources bundled_resources

chmod 755 "$3"
mv -f "$3" "$4"
"./$4" --version
REMOTE_SCRIPT
done

echo ""
echo "==> Done! Binary deployed to ${REMOTE_HOST}:~/$REMOTE_DIR/$BINARY_NAME for users: ${REMOTE_USERS[*]}"
echo "    Bundled resources: ~/$REMOTE_DIR/bundled_resources"
