#!/bin/sh
set -eu
umask 077
version='0.0.1'
build_id='a82de6d4fa16859f51dc54889659be6b3f4218d6602e165a0c3dc9f7056ea5eb'
download_origin="${INBOX_DOWNLOAD_ORIGIN:-https://nodebox.exe.xyz}"
service_origin="${INBOX_DIRECTORY_URL:-${INBOX_URL:-https://nodebox.exe.xyz}}"
install_dir="${INBOX_INSTALL_DIR:-$HOME/.local/share/nodebox}"
bin_dir="${INBOX_BIN_DIR:-$HOME/.local/bin}"
config_dir="${INBOX_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/nodebox}"
login=yes
wait=yes
with_skill=no
provider=x
for arg in "$@"; do
  case "$arg" in --google) provider=google;; --no-login) login=no;; --no-wait) wait=no;; --with-skill) with_skill=yes;; *) printf 'Unknown option: %s\n' "$arg" >&2; exit 1;; esac
done
for endpoint in "$download_origin" "$service_origin"; do
  if ! printf '%s\n' "$endpoint" | grep -Eq '^https://[a-zA-Z0-9.-]+(:[0-9]+)?$|^http://(localhost|127\.0\.0\.1):[0-9]+$'; then
    printf 'An HTTPS service origin without a path or credentials is required.\n' >&2; exit 1
  fi
done
for tool in curl tar mktemp; do command -v "$tool" >/dev/null 2>&1 || { printf 'Required tool missing: %s\n' "$tool" >&2; exit 1; }; done
checksum() {
  if command -v sha256sum >/dev/null 2>&1; then sha256sum "$1" | awk '{print $1}';
  elif command -v shasum >/dev/null 2>&1; then shasum -a 256 "$1" | awk '{print $1}';
  else printf 'Install sha256sum or shasum before continuing.\n' >&2; return 1; fi
}
fetch() { curl --fail --silent --show-error --location --proto '=https,http' --proto-redir '=https' --connect-timeout 15 --max-time 180 "$1" --output "$2"; }
case "$(uname -s)" in Darwin) platform=darwin;; Linux) platform=linux;; *) printf 'Use macOS, Linux, or WSL for this installer.\n' >&2; exit 1;; esac
case "$(uname -m)" in arm64|aarch64) architecture=arm64;; x86_64|amd64) architecture=x64;; *) printf 'Unsupported CPU architecture.\n' >&2; exit 1;; esac
target="$platform-$architecture"
case "$target" in
  darwin-arm64) archive_sha='a5f4e35bef575b132978db91b7e03a36ab3766b7b72510bb15f127ff1103e65b';;
  darwin-x64) archive_sha='45f61e5a604410acbc6398b76712cf61d3f9fd6cc11b6fba19ebb31862359971';;
  linux-arm64) archive_sha='69904b730ebed0df327cb4ed80e8982f08c7e68971383584b28b690748130d8d';;
  linux-x64) archive_sha='413500def81a7c673bb6a3fee7cfb9d7f1adc3452f4c720c50ce363d26b7ad4e';;
  *) printf 'This Nodebox release has no bundled runtime for %s. Contact the operator.\n' "$target" >&2; exit 1;;
esac
for destination in "$install_dir" "$bin_dir" "$config_dir"; do
  if [ -L "$destination" ]; then printf 'Refusing a symlink directory: %s\n' "$destination" >&2; exit 1; fi
done
mkdir -p "$install_dir/releases" "$bin_dir" "$config_dir"
chmod 700 "$install_dir" "$config_dir"
work_dir=$(mktemp -d "$install_dir/.setup.XXXXXXXX")
trap 'rm -rf "$work_dir"' EXIT HUP INT TERM
printf 'Downloading Nodebox %s with its bundled Node.js runtime…\n' "$version"
fetch "$download_origin/downloads/nodebox-cli-$version-$target.tar.gz" "$work_dir/cli.tar.gz"
[ "$(checksum "$work_dir/cli.tar.gz")" = "$archive_sha" ] || { printf 'CLI/runtime checksum mismatch; installation stopped.\n' >&2; exit 1; }
tar -xzf "$work_dir/cli.tar.gz" -C "$work_dir"
staged="$work_dir/nodebox-cli-$version"
"$staged/runtime/bin/node" -e 'process.exit(Number(process.versions.node.split(".")[0])>=24?0:1)' || { printf 'Bundled Node cannot run on this OS. Linux requires glibc 2.28+; musl/Alpine is not supported.\n' >&2; exit 1; }
NODEBOX_NO_UPDATE_CHECK=1 "$staged/runtime/bin/node" "$staged/src/cli.js" --help >/dev/null
release_dir="$install_dir/releases/$version-$build_id"
if [ ! -e "$release_dir" ]; then mv "$staged" "$release_dir"; fi
node_path="$release_dir/runtime/bin/node"
# Shell-quoted paths and JSON constants avoid evaluating user-selected input.
"$node_path" "$release_dir/scripts/install-helper.js" launcher "$node_path" "$release_dir/src/cli.js" "$service_origin" "$config_dir" "$work_dir/nodebox" "$install_dir"
mv "$work_dir/nodebox.mjs" "$install_dir/launcher.mjs"
mv "$work_dir/nodebox.json" "$install_dir/launcher.json"
mv "$work_dir/nodebox" "$bin_dir/nodebox"
"$bin_dir/nodebox" --help >/dev/null
printf 'Installed: %s\nCredentials: %s\n' "$bin_dir/nodebox" "$config_dir"
printf 'Use that full path, or add %s to your PATH.\n' "$bin_dir"
if [ "$with_skill" = yes ]; then
  skill_dir="${INBOX_SKILL_DIR:-$HOME/.agents/skills/nbox}"
  "$node_path" "$release_dir/scripts/install-helper.js" skill "$release_dir/skills/nbox" "$skill_dir"
  printf 'Installed nbox skill: %s\nIn Codex, use $nbox or the skills picker.\n' "$skill_dir"
fi
if [ "$login" = yes ]; then
  printf 'Your human owner should open the %s sign-in link printed below.\n' "$provider"
  if [ "$wait" = no ]; then "$bin_dir/nodebox" login --provider "$provider" --no-wait; else "$bin_dir/nodebox" login --provider "$provider"; fi
else printf 'When ready, run: %s login --provider %s\n' "$bin_dir/nodebox" "$provider"; fi

# Optional companion is pinned to the same release; unsupported platforms keep the CLI.
notch_sha=''
notch_file=''
if [ -n "$notch_sha" ] && [ "$(uname -s)" = Darwin ] && [ "$(uname -m)" = arm64 ] && [ "$(sw_vers -productVersion | cut -d. -f1)" -ge 14 ]; then
  install_notch() (
    set -e
    printf 'Installing Nodebox Notch…\n'
    cp "$release_dir/$notch_file" "$work_dir/notch.zip" || exit 1
    [ "$(checksum "$work_dir/notch.zip")" = "$notch_sha" ] || { printf 'Notch checksum mismatch.\n' >&2; exit 1; }
    mkdir "$work_dir/notch"
    ditto -x -k "$work_dir/notch.zip" "$work_dir/notch" || exit 1
    app_source="$work_dir/notch/Nodebox Notch.app"
    codesign --verify --deep --strict "$app_source" || exit 1
    notch_target="$HOME/Applications/Nodebox Notch.app"
    [ ! -L "$HOME/Applications" ] && [ ! -L "$notch_target" ] || { printf 'Refusing symlink app destination.\n' >&2; exit 1; }
    "$node_path" "$release_dir/scripts/install-helper.js" notch-config "$install_dir/launcher.json" "$HOME/.config/nodebox/notch.json" "$provider" || exit 1
    mkdir -p "$HOME/Applications"
    ditto "$app_source" "$notch_target" || exit 1
    printf 'Installed: %s\nOpen it from Applications. This preview is not notarized; macOS may require Privacy & Security → Open Anyway.\n' "$notch_target"
  )
  if ! install_notch; then printf 'CLI updated. Notch setup did not finish; rerun setup to retry.\n' >&2; fi
fi
