#!/usr/bin/env bash
#
# Cross-compiles the Oz CLI for Linux x86_64 (musl) on macOS and uploads it
# to a remote host via rsync for local remote-server development.
#
# Uses rsync for delta transfers — after the first deploy, only changed bytes
# are sent, which is dramatically faster for iterative development.
#
# Prerequisites:
#   brew install filosottile/musl-cross/musl-cross
#   rustup target add x86_64-unknown-linux-musl
#
# Usage:
#   script/deploy_remote_server --host user@hostname [--profile release]

set -euo pipefail

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

# Defaults
PROFILE_MODE="dev-remote"
HOST=""

usage() {
  cat <<EOF
Usage: $(basename "$0") --host <user@hostname> [OPTIONS]

Cross-compile the Oz CLI for Linux x86_64 and upload it to a remote host.

Required:
  --host <user@hostname>    Remote host to upload to

Options:
  --profile <profile>       Build profile: dev-remote (default, strips symbols), dev, release, or optimized
                            Use --profile dev if you need symbols for remote debugging
  --help                    Show this help message
EOF
  exit 0
}

# Parse arguments
while [[ $# -gt 0 ]]; do
  case "$1" in
    --host)
      HOST="$2"
      shift 2
      ;;
    --profile)
      PROFILE_MODE="$2"
      shift 2
      ;;
    --help)
      usage
      ;;
    *)
      echo "Error: Unknown argument: $1" >&2
      echo "Run with --help for usage." >&2
      exit 1
      ;;
  esac
done

# Validate required arguments
if [[ -z "$HOST" ]]; then
  echo "Error: --host is required." >&2
  echo "Run with --help for usage." >&2
  exit 1
fi

# Validate profile
case "$PROFILE_MODE" in
  dev-remote|dev|release|optimized) ;;
  *)
    echo "Error: Unsupported profile '$PROFILE_MODE'. Use 'dev-remote', 'dev', 'release', or 'optimized'." >&2
    exit 1
    ;;
esac

TARGET="x86_64-unknown-linux-musl"
source "$SCRIPT_DIR/linux/configure_musl_toolchain" "$TARGET"

# Check for musl target
if ! rustup target list --installed 2>/dev/null | grep -q x86_64-unknown-linux-musl; then
  echo "Error: x86_64-unknown-linux-musl target not installed." >&2
  echo "Install it with: rustup target add x86_64-unknown-linux-musl" >&2
  exit 1
fi

# Select the requested Cargo build profile.
case "$PROFILE_MODE" in
  dev-remote)
    CARGO_PROFILE="dev-remote"
    ;;
  dev)
    CARGO_PROFILE="dev"
    ;;
  release)
    CARGO_PROFILE="release"
    ;;
  optimized)
    CARGO_PROFILE="release-lto-debug_assertions"
    ;;
esac

FEATURES="release_bundle,crash_reporting,standalone,agent_mode_debug,remote_codebase_indexing"
WARP_BIN="warp"
BINARY_NAME="oz-local"
REMOTE_DIR=".warp-local/remote-server"
# Global, version-independent resources location read by the daemon. Must
# match BUNDLED_RESOURCES_DIR_NAME in crates/remote_server/src/setup.rs.
BUNDLED_RESOURCES_DIR_NAME="bundled_resources"

# Determine the output directory
CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$WORKSPACE_ROOT/target}"
case "$CARGO_PROFILE" in
  dev)
    OUTPUT_DIR="$CARGO_TARGET_DIR/$TARGET/debug"
    ;;
  *)
    OUTPUT_DIR="$CARGO_TARGET_DIR/$TARGET/$CARGO_PROFILE"
    ;;
esac
BUILT_BINARY="$OUTPUT_DIR/$WARP_BIN"
LOCAL_RESOURCES_DIR="$OUTPUT_DIR/remote-server-resources"

echo "==> Building Oz CLI for $TARGET (profile=$CARGO_PROFILE)"
echo "    Binary: $WARP_BIN -> $BINARY_NAME"
echo "    Features: $FEATURES"
echo ""

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 ""
echo "==> Build complete ($BINARY_SIZE)"
# Prepare the bundled resources tree (skills, settings schema) deployed to
# the global, version-independent location the daemon reads.
rm -rf "$LOCAL_RESOURCES_DIR"
"$WORKSPACE_ROOT/script/prepare_bundled_resources" \
  "$LOCAL_RESOURCES_DIR" \
  local \
  "$CARGO_PROFILE"

# Resolve $HOME on the remote so our upload lands in the same directory the
# Warp client checks. The client runs `test -x ~/.warp-local/...` and lets
# the remote login shell expand `~` to $HOME, while rsync's remote path
# expansion can differ (e.g. on Namespace devboxes, the initial directory
# is /workspaces but $HOME is elsewhere). Using an absolute path derived
# from the remote $HOME keeps both sides consistent.
REMOTE_HOME=$(ssh "$HOST" 'printf %s "$HOME"')
if [[ -z "$REMOTE_HOME" ]]; then
  echo "Error: could not resolve remote \$HOME on $HOST" >&2
  exit 1
fi

REMOTE_ABS_DIR="$REMOTE_HOME/$REMOTE_DIR"

# Ensure rsync is available on the remote host
if ! ssh "$HOST" "command -v rsync" &>/dev/null; then
  echo "==> rsync not found on remote host, installing..."
  ssh "$HOST" "sudo apt-get install -y rsync || sudo yum install -y rsync || sudo dnf install -y rsync || sudo apk add rsync"
  if ! ssh "$HOST" "command -v rsync" &>/dev/null; then
    echo "Error: failed to install rsync on $HOST. Please install it manually and re-run." >&2
    exit 1
  fi
fi

# Ensure the remote install directory exists
ssh "$HOST" "mkdir -p $REMOTE_ABS_DIR"

echo "==> Uploading binary to $HOST:$REMOTE_ABS_DIR/$BINARY_NAME"

# Upload via rsync with delta transfer and compression.
# After the first deploy, only changed bytes are transferred.
rsync -z -t --partial --progress \
  "$BUILT_BINARY" \
  "$HOST:$REMOTE_ABS_DIR/$BINARY_NAME"

# Set executable permissions (done separately for openrsync compatibility on macOS)
ssh "$HOST" "chmod 755 $REMOTE_ABS_DIR/$BINARY_NAME"

echo "==> Uploading bundled resources to $HOST:$REMOTE_ABS_DIR/$BUNDLED_RESOURCES_DIR_NAME"
rsync -z -rlt --delete --partial --progress \
  "$LOCAL_RESOURCES_DIR/" \
  "$HOST:$REMOTE_ABS_DIR/$BUNDLED_RESOURCES_DIR_NAME/"

echo "==> Stopping stale remote-server daemons on $HOST"
ssh "$HOST" bash <<'EOF'
set -euo pipefail

REMOTE_SERVER_ROOT="$HOME/.warp-local/remote-server"
shopt -s nullglob

for pid_file in "$REMOTE_SERVER_ROOT"/*/server.pid; do
  daemon_dir="$(dirname "$pid_file")"
  pid="$(cat "$pid_file" 2>/dev/null || true)"
  if [[ -z "$pid" || ! "$pid" =~ ^[0-9]+$ ]]; then
    rm -f "$daemon_dir/server.sock" "$pid_file"
    continue
  fi

  if [[ ! -r "/proc/$pid/cmdline" ]]; then
    rm -f "$daemon_dir/server.sock" "$pid_file"
    continue
  fi

  cmdline="$(tr '\0' ' ' <"/proc/$pid/cmdline" || true)"
  if [[ "$cmdline" != *remote-server-daemon* ]]; then
    continue
  fi

  echo "    Stopping stale daemon pid=$pid dir=$daemon_dir"
  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 daemon pid=$pid"
    kill -9 "$pid" 2>/dev/null || true
  fi
  rm -f "$daemon_dir/server.sock" "$pid_file"
done
EOF

echo ""
echo "==> Done! Binary deployed to $HOST:$REMOTE_ABS_DIR/$BINARY_NAME"
echo "    Bundled resources: $REMOTE_ABS_DIR/$BUNDLED_RESOURCES_DIR_NAME"
echo "    (resolved from ~/$REMOTE_DIR on remote)"
