#!/usr/bin/env bash
set -Eeu

install_locale_usable() {
  local _locale="$1" _norm _entry

  [ -n "$_locale" ] || return 1
  case "$_locale" in
    C|C.*|POSIX*) return 0 ;;
  esac
  command -v locale >/dev/null 2>&1 || return 1
  _norm=$(printf '%s' "$_locale" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]' | tr '_' '-')
  while IFS= read -r _entry; do
    [ -n "$_entry" ] || continue
    _entry=$(printf '%s' "$_entry" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]' | tr '_' '-')
    if [ "$_entry" = "$_norm" ]; then
      return 0
    fi
  done <<EOF
$(locale -a 2>/dev/null)
EOF
  return 1
}

install_sanitize_locale_env() {
  if [ -n "${LC_ALL:-}" ] && ! install_locale_usable "$LC_ALL"; then
    unset LC_ALL
  fi
}

install_sanitize_locale_env

SCRIPT_DIR=$(CDPATH= cd -- "$(dirname "$0")" && pwd)

INSTALL_PUBLIC_BASE_URL="https://downloads.taosdata.com/apex"
INSTALL_LAN_BASE_URL="https://nexus.tdengine.net/repository/platform/apex"
INSTALL_LAN_PROBE_HOST="platform.tdengine.net"
INSTALL_LAN_PROBE_IP="103.114.192.2"

install_is_private_ip() {
  local ip="$1"

  case "$ip" in
    10.*|192.168.*|172.1[6-9].*|172.2[0-9].*|172.3[0-1].*) return 0 ;;
  esac
  return 1
}

install_probe_ip_via_ping() {
  local host="${INSTALL_LAN_PROBE_HOST}" ping_out ip

  if ! command -v ping >/dev/null 2>&1; then
    return 1
  fi

  case "$(uname -s 2>/dev/null || true)" in
    Darwin)
      ping_out=$(ping -c 1 -W 3000 "$host" 2>/dev/null) || return 1
      ;;
    *)
      ping_out=$(ping -c 1 -W 3 "$host" 2>/dev/null) || ping_out=$(ping -c 1 -w 3 "$host" 2>/dev/null) || return 1
      ;;
  esac

  ip=$(printf '%s\n' "$ping_out" | head -n1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -n1)
  [ -n "$ip" ] || return 1
  printf '%s\n' "$ip"
}

install_probe_origin_via_curl() {
  local origin=""

  if ! command -v curl >/dev/null 2>&1; then
    return 1
  fi

  origin=$(curl -fsS --connect-timeout 5 --max-time 10 https://httpbin.org/ip 2>/dev/null \
    | sed -n 's/.*"origin"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -n1)
  [ -n "$origin" ] || return 1
  printf '%s\n' "$origin"
}

install_base_url_implies_lan() {
  case "${APEX_BASE_URL:-}" in
    *://nexus.tdengine.net/*|*://release.tdengine.net/*|*://registry.tdengine.net/*|*://platform.tdengine.net/*)
      return 0
      ;;
  esac
  return 1
}

install_detect_lan_for_bootstrap() {
  local ip origin

  case "${APEX_NETWORK_REGION:-}" in
    lan) return 0 ;;
  esac

  if install_base_url_implies_lan; then
    return 0
  fi

  ip=$(install_probe_ip_via_ping 2>/dev/null || true)
  if [ -n "$ip" ]; then
    if install_is_private_ip "$ip" || [ "$ip" = "$INSTALL_LAN_PROBE_IP" ]; then
      return 0
    fi
  fi

  origin=$(install_probe_origin_via_curl 2>/dev/null || true)
  if [ -n "$origin" ] && [ "$origin" = "$INSTALL_LAN_PROBE_IP" ]; then
    return 0
  fi

  return 1
}

install_resolve_default_base_url() {
  if [ -n "${APEX_BASE_URL:-}" ]; then
    printf '%s' "${APEX_BASE_URL%/}"
    return 0
  fi
  if install_detect_lan_for_bootstrap; then
    printf '%s' "$INSTALL_LAN_BASE_URL"
    return 0
  fi
  printf '%s' "$INSTALL_PUBLIC_BASE_URL"
}

install_detect_lang() {
  if [ -n "${APEX_LANG:-}" ]; then
    case "$APEX_LANG" in
      en|en_*|EN|EN_*) printf 'en\n'; return 0 ;;
      zh|cn|zh_*|cn_*|*Chinese*) printf 'zh\n'; return 0 ;;
      *) printf 'en\n'; return 0 ;;
    esac
  fi
  local locale="${LANG:-${LC_ALL:-${LC_MESSAGES:-}}}"
  case "$locale" in
    zh*|*zh_CN*|*zh_TW*|*zh_HK*|*zh-Hans*|*zh-Hant*|*Chinese*) printf 'zh\n'; return 0 ;;
  esac
  if [ "$(uname -s 2>/dev/null || true)" = "Darwin" ] && command -v defaults >/dev/null 2>&1; then
    local apple_locale
    apple_locale=$(defaults read -g AppleLocale 2>/dev/null || true)
    case "$apple_locale" in
      zh_*|zh-*|*Chinese*) printf 'zh\n'; return 0 ;;
    esac
  fi
  printf 'en\n'
}

BASE_URL="$(install_resolve_default_base_url)"
VERSION="${APEX_VERSION:-latest}"
INSTALL_MODE="${APEX_INSTALL_MODE:-apex}"
INSTALL_BOOTSTRAP_DIR=""
PACK_OFFLINE=0
DOWNLOAD_ONLY=0
BUILD_OFFLINE_BUNDLE=0
OFFLINE_INSTALL=0
OUTPUT_PATH=""
BUNDLE_PATH=""
OFFLINE_DEPLOYMENT=""
CACHE_DIR=""
USER_SET_APEX_HOME=0
USER_SET_CACHE_DIR=0

os_release_field() {
  local key="$1"
  local line value
  [ -r /etc/os-release ] || return 1
  line=$(grep -m1 "^${key}=" /etc/os-release 2>/dev/null || true)
  [ -n "$line" ] || return 1
  value=${line#"${key}="}
  value=${value#\"}
  value=${value%\"}
  printf '%s' "$value"
}

normalize_version_tag() {
  local version="$1"

  case "$version" in
    latest) printf '%s\n' "$version" ;;
    v*) printf '%s\n' "$version" ;;
    *) printf 'v%s\n' "$version" ;;
  esac
}

package_archive_name() {
  local version="$1"
  local platform_os="$2"
  local platform_arch="$3"
  local tag

  if [ "$version" = "latest" ]; then
    printf 'apex-%s-%s.tar.gz\n' "$platform_os" "$platform_arch"
    return 0
  fi

  tag=$(normalize_version_tag "$version")
  printf 'apex-%s-%s-%s.tar.gz\n' "$tag" "$platform_os" "$platform_arch"
}

install_is_nexus_package_base() {
  local base="${1%/}"
  case "$base" in
    https://nexus.tdengine.net/repository/platform/apex) return 0 ;;
    https://nexus.tdengine.net/repository/platform/apex/latest) return 0 ;;
    */nexus.tdengine.net/repository/platform/apex) return 0 ;;
    */nexus.tdengine.net/repository/platform/apex/latest) return 0 ;;
  esac
  return 1
}

install_strip_package_base_suffix() {
  local base="${1%/}"
  while :; do
    case "$base" in
      */latest) base="${base%/latest}" ;;
      *) break ;;
    esac
  done
  printf '%s' "$base"
}

resolve_install_package_base_url() {
  local base="${BASE_URL%/}"
  local version="${VERSION:-latest}"
  local tag=""

  base=$(install_strip_package_base_suffix "$base")
  tag=$(normalize_version_tag "$version")
  if [ "${base##*/}" = "$tag" ]; then
    printf '%s' "$base"
    return 0
  fi
  if install_is_nexus_package_base "$base"; then
    if [ "$version" = "latest" ]; then
      printf '%s/latest' "$base"
      return 0
    fi
    printf '%s/%s' "$base" "$tag"
    return 0
  fi
  if [ "$version" != "latest" ]; then
    printf '%s/%s' "$base" "$tag"
    return 0
  fi
  printf '%s' "$base"
}

install_try_download_release_archive() {
  local url="$1"
  local dest="$2"
  local retry_url=""
  local release_root=""
  local legacy_version=""
  local archive=""

  if curl -fsSL "$url" -o "$dest"; then
    printf '%s' "$url"
    return 0
  fi

  if [[ "$url" =~ ^(.*/apex)/v([^/]+)/(apex-v.+)$ ]]; then
    release_root="${BASH_REMATCH[1]}"
    legacy_version="${BASH_REMATCH[2]}"
    archive="${BASH_REMATCH[3]}"
    if [[ "$url" == *nexus.tdengine.net/repository/platform/apex/* ]]; then
      retry_url="${release_root}/${legacy_version}/${archive}"
    else
      retry_url="${release_root}/${archive}"
    fi
    if curl -fsSL "$retry_url" -o "$dest"; then
      printf '%s' "$retry_url"
      return 0
    fi
  fi

  # Back-compat for older install.sh builds and mis-set APEX_BASE_URL without /latest/.
  if [[ "$url" =~ ^(.*/apex)/(apex-.+)$ ]] \
    && [[ "$url" == *nexus.tdengine.net/repository/platform/apex/* ]] \
    && [[ "$url" != */latest/* ]]; then
    retry_url="${BASH_REMATCH[1]}/latest/${BASH_REMATCH[2]}"
    if curl -fsSL "$retry_url" -o "$dest"; then
      printf '%s' "$retry_url"
      return 0
    fi
  fi
  return 1
}

detect_platform() {
  PLATFORM_OS=""
  PLATFORM_ARCH=""

  case "$(uname -s | tr '[:upper:]' '[:lower:]')" in
    linux) PLATFORM_OS="linux" ;;
    darwin) PLATFORM_OS="darwin" ;;
    *)
      echo "unsupported OS: $(uname -s)" >&2
      return 1
      ;;
  esac

  case "$(uname -m)" in
    x86_64|amd64) PLATFORM_ARCH="x64" ;;
    aarch64|arm64) PLATFORM_ARCH="arm64" ;;
    *)
      echo "unsupported architecture: $(uname -m)" >&2
      return 1
      ;;
  esac
}

chmod_deploy_scripts() {
  local dest="$1"

  chmod +x "${dest}/linux/deploy.sh" 2>/dev/null || true
  chmod +x "${dest}/linux/configure-docker-registry.sh" 2>/dev/null || true
  chmod +x "${dest}/linux/offline-bundle.sh" 2>/dev/null || true
}

bootstrap_release_package_download_extract() {
  local archive url package_base

  # deploy-scripts/ is never downloaded file-by-file from CDN/Nexus.
  # This is the only network fetch for deployment helpers: the platform release archive.
  archive=$(package_archive_name "${VERSION:-latest}" "$PLATFORM_OS" "$PLATFORM_ARCH")
  package_base=$(resolve_install_package_base_url)
  url="${package_base%/}/${archive}"

  if [ "$DOWNLOAD_ONLY" != "1" ] && [ "$PACK_OFFLINE" != "1" ]; then
    echo "Downloading release package: ${url}" >&2
  fi
  if ! resolved_url=$(install_try_download_release_archive "$url" "${INSTALL_BOOTSTRAP_DIR}/${archive}"); then
    echo "failed to download release package: ${url}" >&2
    if install_is_nexus_package_base "$(install_strip_package_base_suffix "${BASE_URL}")"; then
      echo "hint: Nexus release archives live under ${BASE_URL%/}/latest/ (or ${BASE_URL%/}/<version>/)" >&2
    elif [ -z "${APEX_BASE_URL:-}" ] && [ "$BASE_URL" = "$INSTALL_PUBLIC_BASE_URL" ]; then
      echo "hint: on an internal network, install.sh auto-detects LAN via platform.tdengine.net;" >&2
      echo "  if detection fails, set APEX_BASE_URL=https://nexus.tdengine.net/repository/platform/apex" >&2
    fi
    return 1
  fi
  url="$resolved_url"
  if ! tar -xzf "${INSTALL_BOOTSTRAP_DIR}/${archive}" -C "$INSTALL_BOOTSTRAP_DIR"; then
    echo "failed to extract release package: ${archive}" >&2
    return 1
  fi
  if [ ! -f "${INSTALL_BOOTSTRAP_DIR}/deploy-scripts/linux/apex-common.sh" ]; then
    echo "release package missing deploy-scripts/linux/apex-common.sh" >&2
    return 1
  fi
  if [ ! -f "${INSTALL_BOOTSTRAP_DIR}/deploy-scripts/linux/deploy.sh" ]; then
    echo "release package missing deploy-scripts/linux/deploy.sh" >&2
    return 1
  fi
  return 0
}

cleanup_bootstrap_dir() {
  if [ -n "${INSTALL_BOOTSTRAP_DIR:-}" ] && [ -d "$INSTALL_BOOTSTRAP_DIR" ]; then
    rm -rf "$INSTALL_BOOTSTRAP_DIR"
    INSTALL_BOOTSTRAP_DIR=""
  fi
}

on_install_interrupt() {
  local exit_code="${1:-130}"
  trap - INT TERM
  printf '\n' >/dev/tty 2>/dev/null || printf '\n' >&2
  cleanup_bootstrap_dir
  exit "$exit_code"
}

install_require_tar() {
  if command -v tar >/dev/null 2>&1; then
    return 0
  fi
  case "$(install_detect_lang)" in
    zh)
      echo "错误：未找到 tar 命令。部署依赖 tar 解压安装包，请自行安装 tar 后重新运行。" >&2
      ;;
    *)
      echo "Error: tar command not found. Deployment requires tar to extract packages. Install tar and re-run." >&2
      ;;
  esac
  printf '\n' >&2
  return 1
}

install_require_port_check_tool() {
  if command -v ss >/dev/null 2>&1 \
    || command -v lsof >/dev/null 2>&1 \
    || command -v netstat >/dev/null 2>&1; then
    return 0
  fi
  case "$(install_detect_lang)" in
    zh)
      echo "错误：未找到 ss、lsof 或 netstat 命令。安装前端口检查需要上述工具之一，请安装后重新运行。" >&2
      ;;
    *)
      echo "Error: none of ss, lsof, or netstat was found. Pre-install port checks require one of these tools. Install one and re-run." >&2
      ;;
  esac
  printf '\n' >&2
  return 1
}

bootstrap_release_package() {
  if ! detect_platform; then
    return 1
  fi

  cleanup_bootstrap_dir
  INSTALL_BOOTSTRAP_DIR="$(mktemp -d)"

  if ! bootstrap_release_package_download_extract; then
    cleanup_bootstrap_dir
    return 1
  fi

  if [ "$PACK_OFFLINE" = "1" ] \
    && [ ! -f "${INSTALL_BOOTSTRAP_DIR}/deploy-scripts/linux/offline-bundle.sh" ]; then
    echo "release package missing deploy-scripts/linux/offline-bundle.sh" >&2
    echo "publish a release that includes offline support to $(resolve_install_package_base_url)" >&2
    cleanup_bootstrap_dir
    return 1
  fi

  return 0
}

# install.sh is published at the apex repository root, not under versioned
# subdirectories such as apex/v0.3.37-rc1/ or apex/latest/.
install_public_base_url() {
  local base="${1:-${BASE_URL}}"
  local last

  base="${base%/}"
  last="${base##*/}"
  case "$last" in
    latest|v*)
      printf '%s' "${base%/*}"
      ;;
    apex|platform)
      printf '%s' "$base"
      ;;
    *)
      if [[ "$last" =~ [0-9] ]]; then
        printf '%s' "${base%/*}"
      else
        printf '%s' "$base"
      fi
      ;;
  esac
}

install_format_docker_command() {
  local install_root pipe_env version_arg install_url

  install_root=$(install_public_base_url)
  install_url="${install_root}/install.sh"
  pipe_env=""
  version_arg=""
  if [ -n "${APEX_BASE_URL:-}" ]; then
    pipe_env="APEX_BASE_URL='${BASE_URL}' "
  fi
  if [ -n "${VERSION:-}" ] && [ "$VERSION" != "latest" ]; then
    version_arg=" -v ${VERSION}"
  fi
  printf 'curl -fsSL %s | %sbash -s -- -m docker%s' "$install_url" "$pipe_env" "$version_arg"
}

install_reject_unsupported_apex_host() {
  local mode="$1"
  local lang docker_cmd

  if [ "$mode" != "apex" ]; then
    return 0
  fi
  case "$(uname -s 2>/dev/null || true)" in
    Darwin)
      lang=$(install_detect_lang)
      docker_cmd=$(install_format_docker_command)
      case "$lang" in
        zh)
          echo "错误：macOS 不支持 Apex 裸机部署模式（-m apex）。" >&2
          echo "请改用 Docker 模式安装：${docker_cmd}" >&2
          ;;
        *)
          echo "Error: bare-metal Apex mode (-m apex) is not supported on macOS." >&2
          echo "Use Docker mode instead: ${docker_cmd}" >&2
          ;;
      esac
      printf '\n' >&2
      return 1
      ;;
  esac
  return 0
}

load_apex_common() {
  local common=""

  if [ -n "${INSTALL_BOOTSTRAP_DIR:-}" ]; then
    common="${INSTALL_BOOTSTRAP_DIR}/deploy-scripts/linux/apex-common.sh"
    if [ ! -f "$common" ]; then
      return 1
    fi
    # shellcheck source=/dev/null
    source "$common"
    return 0
  fi

  common="${APEX_HOME:-}/deploy-scripts/linux/apex-common.sh"
  if [ -f "$common" ]; then
    # shellcheck source=/dev/null
    source "$common"
    return 0
  fi
  return 1
}

load_install_ui() {
  local deploy=""

  APEX_UI_LIBRARY=1
  if [ -n "${INSTALL_BOOTSTRAP_DIR:-}" ]; then
    deploy="${INSTALL_BOOTSTRAP_DIR}/deploy-scripts/linux/deploy.sh"
    if [ ! -f "$deploy" ]; then
      return 1
    fi
    # shellcheck source=/dev/null
    source "$deploy"
    apex_ui_init
    return 0
  fi

  deploy="${APEX_HOME:-}/deploy-scripts/linux/deploy.sh"
  if [ -f "$deploy" ]; then
    # shellcheck source=/dev/null
    source "$deploy"
    apex_ui_init
    return 0
  fi
  return 1
}

install_host_supports_tdmodel() {
  apex_host_supports_tdmodel
}

usage() {
  cat <<'EOF'
Usage: install.sh [-m apex|docker] [-v VERSION] [-H APEX_HOME] [-C CACHE_DIR]
                  [--build-offline-bundle -o OUTPUT.tar.gz]
                  [--download-only] [--pack-offline -o OUTPUT.tar.gz]
                  [--offline [-b BUNDLE]] [-f DEPLOYMENT.yaml]

Modes:
  apex    Download, install, and deploy Apex on this machine.
  docker  Download Docker assets and deploy the container stack.

Options:
  -v, --version VERSION   Apex package version (default: latest or APEX_VERSION)
  -H, --apex-home PATH    Apex data directory (default: ~/.apex)
  -C, --cache PATH        Artifact cache directory (default: <apex-home>/cache)
  -f, --deployment FILE  Deployment profile YAML (default: from APEX_DEPLOY_PROFILE, else All-in-One)
  --build-offline-bundle  Download artifacts and build an offline bundle (online machine)
  --download-only         Download artifacts into cache only (like apex prepare; no deploy)
  --pack-offline          Build an offline bundle (online machine only)
  -o, --output PATH       Output archive for --build-offline-bundle / --pack-offline
  --offline               Install from an offline bundle without downloading
  -b, --bundle PATH       Offline bundle archive or extracted directory

Examples:
  curl -fsSL .../install.sh | bash -s -- -m apex -v 0.3.2-test
  bash install.sh --build-offline-bundle -m apex -o ./apex-offline-linux-x64.tar.gz
  bash install.sh --download-only -m apex
  bash install.sh --pack-offline -m apex -o ./apex-offline-linux-x64.tar.gz
  bash install.sh --offline -b ./apex-offline-linux-x64.tar.gz -H /data/apex-home
EOF
}

while [ $# -gt 0 ]; do
  case "$1" in
    -m|--mode)
      if [ $# -lt 2 ]; then
        echo "missing value for $1" >&2
        usage >&2
        exit 2
      fi
      INSTALL_MODE="$2"
      shift 2
      ;;
    -v|--version)
      if [ $# -lt 2 ]; then
        echo "missing value for $1" >&2
        usage >&2
        exit 2
      fi
      VERSION="$2"
      shift 2
      ;;
    -H|--apex-home)
      if [ $# -lt 2 ]; then
        echo "missing value for $1" >&2
        usage >&2
        exit 2
      fi
      APEX_HOME="$2"
      USER_SET_APEX_HOME=1
      shift 2
      ;;
    -C|--cache)
      if [ $# -lt 2 ]; then
        echo "missing value for $1" >&2
        usage >&2
        exit 2
      fi
      CACHE_DIR="$2"
      USER_SET_CACHE_DIR=1
      shift 2
      ;;
    -f|--deployment)
      if [ $# -lt 2 ]; then
        echo "missing value for $1" >&2
        usage >&2
        exit 2
      fi
      OFFLINE_DEPLOYMENT="$2"
      shift 2
      ;;
    --pack-offline)
      PACK_OFFLINE=1
      shift
      ;;
    --build-offline-bundle)
      BUILD_OFFLINE_BUNDLE=1
      shift
      ;;
    --download-only)
      DOWNLOAD_ONLY=1
      shift
      ;;
    --offline)
      OFFLINE_INSTALL=1
      APEX_OFFLINE=1
      shift
      ;;
    -o|--output)
      if [ $# -lt 2 ]; then
        echo "missing value for $1" >&2
        usage >&2
        exit 2
      fi
      OUTPUT_PATH="$2"
      shift 2
      ;;
    -b|--bundle)
      if [ $# -lt 2 ]; then
        echo "missing value for $1" >&2
        usage >&2
        exit 2
      fi
      BUNDLE_PATH="$2"
      shift 2
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "unknown argument: $1" >&2
      usage >&2
      exit 2
      ;;
  esac
done

case "$INSTALL_MODE" in
  apex|docker) ;;
  *)
    echo "unsupported install mode: $INSTALL_MODE (expected apex or docker)" >&2
    exit 2
    ;;
esac

if [ "$BUILD_OFFLINE_BUNDLE" = "1" ]; then
  if [ "$DOWNLOAD_ONLY" = "1" ] || [ "$PACK_OFFLINE" = "1" ] || [ "$OFFLINE_INSTALL" = "1" ]; then
    echo "--build-offline-bundle cannot be combined with --download-only, --pack-offline, or --offline" >&2
    exit 2
  fi
  if [ -z "$OUTPUT_PATH" ]; then
    echo "--output is required for --build-offline-bundle" >&2
    exit 2
  fi
fi

load_offline_bundle_helpers() {
  local helper="" candidates=()

  if [ "$OFFLINE_INSTALL" = "1" ]; then
    candidates=(
      "${SCRIPT_DIR}/apex-home/deploy-scripts/linux/offline-bundle.sh"
      "${SCRIPT_DIR}/deploy-scripts/linux/offline-bundle.sh"
    )
  fi
  candidates+=(
    "${INSTALL_BOOTSTRAP_DIR:-}/deploy-scripts/linux/offline-bundle.sh"
    "${APEX_HOME:-}/deploy-scripts/linux/offline-bundle.sh"
  )
  if [ "$OFFLINE_INSTALL" != "1" ]; then
    candidates+=(
      "${SCRIPT_DIR}/apex-home/deploy-scripts/linux/offline-bundle.sh"
      "${SCRIPT_DIR}/deploy-scripts/linux/offline-bundle.sh"
    )
  fi

  for helper in "${candidates[@]}"; do
    if [ -f "$helper" ]; then
      # shellcheck source=deploy-scripts/linux/offline-bundle.sh
      source "$helper"
      return 0
    fi
  done
  echo "offline-bundle.sh not found under ${APEX_HOME:-~/.apex}/deploy-scripts/linux" >&2
  echo "deploy-scripts come from the release package or offline bundle; refresh with install.sh after publishing a new apex release." >&2
  return 1
}

install_assert_safe_apex_home_path() {
  local home="${1:-}"

  if [ -z "$home" ]; then
    echo "APEX_HOME must not be empty" >&2
    return 1
  fi

  case "$home" in
    /|/usr|/usr/local|/bin|/etc|/var|/opt|/root)
      echo "refusing to modify Apex data under unsafe path: $home" >&2
      return 1
      ;;
  esac

  if [ -n "${HOME:-}" ] && [ "$home" = "$HOME" ]; then
    echo "refusing to use home directory as APEX_HOME: $home (use ${HOME}/.apex instead)" >&2
    return 1
  fi

  return 0
}

sync_apex_home_from_release_package() {
  if [ -z "${INSTALL_BOOTSTRAP_DIR:-}" ] || [ ! -d "${INSTALL_BOOTSTRAP_DIR}/manifests" ]; then
    if ! bootstrap_release_package; then
      return 1
    fi
  fi
  if ! install_assert_safe_apex_home_path "$APEX_HOME"; then
    return 1
  fi
  mkdir -p "$APEX_HOME"
  rm -rf "${APEX_HOME}/manifests" "${APEX_HOME}/scripts" "${APEX_HOME}/deploy-scripts"
  cp -R "${INSTALL_BOOTSTRAP_DIR}/manifests" "${APEX_HOME}/manifests"
  cp -R "${INSTALL_BOOTSTRAP_DIR}/scripts" "${APEX_HOME}/scripts"
  cp -R "${INSTALL_BOOTSTRAP_DIR}/deploy-scripts" "${APEX_HOME}/deploy-scripts"
  chmod_deploy_scripts "${APEX_HOME}/deploy-scripts"
  return 0
}

install_apex_cli_from_bootstrap() {
  local binary=""

  if [ -z "${INSTALL_BOOTSTRAP_DIR:-}" ]; then
    echo "release package bootstrap directory is not available" >&2
    return 1
  fi
  if ! detect_platform; then
    return 1
  fi
  binary="${INSTALL_BOOTSTRAP_DIR}/apex-${PLATFORM_OS}-${PLATFORM_ARCH}"
  if [ ! -x "$binary" ] && [ ! -f "$binary" ]; then
    echo "release binary not found: $binary" >&2
    return 1
  fi
  if [ -z "${INSTALL_DIR:-}" ]; then
    INSTALL_DIR="/usr/local/bin"
    if [ ! -w "$INSTALL_DIR" ]; then
      INSTALL_DIR="${HOME}/.local/bin"
    fi
  fi
  mkdir -p "$INSTALL_DIR"
  install -m 0755 "$binary" "${INSTALL_DIR}/apex"
  export PATH="${INSTALL_DIR}:${PATH}"
  return 0
}

ensure_apex_home_populated_for_pack() {
  sync_apex_home_from_release_package
}

ensure_apex_cli_for_pack() {
  install_apex_cli_from_bootstrap
}

install_prompt_apex_home() {
  local input=""

  if declare -F apex_i18n >/dev/null 2>&1; then
    printf '%s' "$(apex_i18n apex_home_prompt "$APEX_HOME")" > /dev/tty
  else
    case "$(install_detect_lang)" in
      zh) printf 'Apex 数据目录 [%s]: ' "$APEX_HOME" > /dev/tty ;;
      *) printf 'Apex home [%s]: ' "$APEX_HOME" > /dev/tty ;;
    esac
  fi
  read -r input < /dev/tty
  if [ -n "$input" ]; then
    APEX_HOME="$input"
  fi
}

resolve_install_apex_home() {
  if [ -z "${APEX_HOME:-}" ]; then
    APEX_HOME="${HOME}/.apex"
    if [ "$USER_SET_APEX_HOME" != "1" ] && [ -r /dev/tty ] && [ -w /dev/tty ]; then
      install_prompt_apex_home
    fi
  fi
  export APEX_HOME
}

resolve_install_cache_dir() {
  if [ -z "$CACHE_DIR" ]; then
    CACHE_DIR="${APEX_HOME}/cache"
  fi
  export APEX_CACHE_DIR="$CACHE_DIR"
}

write_config() {
  local base_url
  mkdir -p "$APEX_HOME"
  base_url=$(apex_config_base_url_for_install 2>/dev/null || true)
  {
    printf 'apex_home: "%s"\n' "$APEX_HOME"
    printf 'install_mode: %s\n' "$INSTALL_MODE"
    printf 'telemetry_enabled: true\n'
    if [ -n "$base_url" ]; then
      printf 'base_url: %s\n' "$base_url"
    fi
  } > "${APEX_HOME}/config.yaml"
  if [ "${HOME}/.apex" != "$APEX_HOME" ]; then
    mkdir -p "${HOME}/.apex"
    cp "${APEX_HOME}/config.yaml" "${HOME}/.apex/config.yaml"
  fi
}

install_offline_apply_bundle_profile_from_meta() {
  local root="${1:-$SCRIPT_DIR}"
  local meta="${root}/bundle.meta.yaml"
  local deployment=""

  if [ -n "${APEX_DEPLOY_PROFILE:-}" ]; then
    return 0
  fi
  if [ -n "${OFFLINE_DEPLOYMENT:-}" ]; then
    deployment=$(basename "$OFFLINE_DEPLOYMENT")
  elif [ -f "$meta" ]; then
    deployment=$(awk '/^source:/{flag=1;next} flag && /^  deployment:/{print $2; exit} flag && /^[^ ]/{flag=0}' "$meta")
  fi
  if [ -z "$deployment" ]; then
    return 0
  fi

  case "$deployment" in
    deployment-tsdb-only.yaml|deployment-tsdb.yaml)
      export APEX_DEPLOY_PROFILE='TSDB-Enterprise'
      ;;
    deployment-idmp-only.yaml|deployment-idmp.yaml)
      export APEX_DEPLOY_PROFILE='IDMP-Enterprise'
      ;;
    deployment-single-node.yaml|deployment-single-node-no-tdmodel.yaml)
      export APEX_DEPLOY_PROFILE='All-in-One'
      ;;
  esac
}

run_offline_install_flow() {
  export OFFLINE_INSTALL APEX_OFFLINE=1 OFFLINE_DEPLOYMENT
  install_offline_apply_bundle_profile_from_meta "$SCRIPT_DIR"
  if ! load_offline_bundle_helpers; then
    exit 1
  fi
  resolve_install_apex_home
  resolve_install_cache_dir
  if ! install_require_root_for_offline; then
    exit 1
  fi
  apex_offline_install_from_bundle "$BUNDLE_PATH" "$SCRIPT_DIR" "$APEX_HOME"
  exit $?
}

install_require_root_for_offline() {
  if [ "$INSTALL_MODE" = "apex" ] && [ "$(id -u)" -ne 0 ]; then
    echo "Apex bare-metal offline install requires root privileges." >&2
    return 1
  fi
  return 0
}

init_offline_builder_context() {
  resolve_install_apex_home
  resolve_install_cache_dir
  export APEX_HOME APEX_CACHE_DIR="$CACHE_DIR"

  if [ "$INSTALL_MODE" != "apex" ]; then
    echo "offline builder currently supports -m apex only" >&2
    return 1
  fi
  if ! install_require_tar; then
    return 1
  fi
  if ! bootstrap_release_package; then
    echo "failed to bootstrap release package from ${BASE_URL}" >&2
    return 1
  fi
  trap cleanup_bootstrap_dir EXIT

  if ! ensure_apex_home_populated_for_pack; then
    echo "failed to populate ${APEX_HOME} from release package" >&2
    return 1
  fi

  if ! load_apex_common; then
    echo "failed to load apex-common.sh from release package" >&2
    return 1
  fi
  if ! load_install_ui; then
    apex_ui_init() { :; }
    apex_ui_box_open() { printf '\n%s\n\n' "=== $1 ==="; }
    apex_ui_box_line() { printf '  %s\n' "$1"; }
    apex_ui_box_blank() { printf '\n'; }
    apex_ui_box_kv() { printf '  %-12s %s\n' "$1" "$2"; }
    apex_ui_box_wrap() { printf '  %s\n' "$1"; }
    apex_ui_box_close() { printf '\n'; }
    apex_ui_init
  fi

  write_config
  resolve_install_cli_dir

  if ! ensure_apex_cli_for_pack; then
    echo "failed to install Apex CLI for offline builder" >&2
    return 1
  fi
  return 0
}

run_pack_offline_flow() {
  export OFFLINE_DEPLOYMENT INSTALL_SCRIPT_PATH="${SCRIPT_DIR}/install.sh"
  if [ -z "$OUTPUT_PATH" ]; then
    echo "--output is required for --pack-offline" >&2
    exit 2
  fi
  if ! init_offline_builder_context; then
    exit 1
  fi
  if ! load_offline_bundle_helpers; then
    exit 1
  fi
  apex_offline_pack_bundle "$APEX_HOME" "$CACHE_DIR" "$OFFLINE_DEPLOYMENT" "$OUTPUT_PATH"
  exit $?
}

resolve_install_cli_dir() {
  if [ -n "${APEX_INSTALL_DIR:-}" ]; then
    INSTALL_DIR="$APEX_INSTALL_DIR"
  elif [ -d /usr/local/bin ] && [ -w /usr/local/bin ]; then
    INSTALL_DIR="/usr/local/bin"
  else
    INSTALL_DIR="${HOME}/.local/bin"
  fi
  export INSTALL_DIR
}

print_download_only_complete() {
  apex_ui_box_open "$(apex_i18n download_only_complete_title)" "33"
  apex_ui_box_blank
  apex_ui_box_wrap "$(apex_i18n download_only_complete_intro)"
  apex_ui_box_blank
  apex_ui_box_kv "$(apex_i18n label_apex_cli)" "${INSTALL_DIR}/apex" "90" "32"
  apex_ui_box_kv "$(apex_i18n label_apex_home)" "${APEX_HOME}" "90" "0"
  apex_ui_box_kv "$(apex_i18n label_cache_dir)" "${CACHE_DIR}" "90" "0"
  apex_ui_box_blank
  apex_ui_box_kv_wrap "$(apex_i18n download_only_pack_hint)" \
    "bash install.sh --build-offline-bundle -m apex -o ./apex-offline-linux-x64.tar.gz"
  apex_ui_box_close
}

run_download_only_prepare() {
  local deployment="" apex_cli="" normalized="" resolved=""

  apex_cli=$(command -v apex)
  if [ -z "$apex_cli" ]; then
    echo "apex CLI not found in PATH" >&2
    return 1
  fi

  if load_offline_bundle_helpers 2>/dev/null; then
    deployment=$(apex_offline_default_deployment "$APEX_HOME") || return 1
    apex_offline_run_prepare "$APEX_HOME" "$CACHE_DIR" "$deployment" "$apex_cli" || return 1
    apex_offline_validate_cache_dir "$CACHE_DIR" || return 1
    return 0
  fi

  normalized=$(apex_normalize_deploy_profile "${APEX_DEPLOY_PROFILE:-All-in-One}") || return 1
  resolved=$(apex_resolve_profile_deployment_file "$APEX_HOME" "$normalized") || return 1
  echo "Preparing deployment artifacts ($(basename "$resolved"))..."
  if ! APEX_HOME="$APEX_HOME" "$apex_cli" prepare -f "$resolved" \
    --manifests "${APEX_HOME}/manifests" \
    --cache "$CACHE_DIR" \
    --summary; then
    return 1
  fi
  if [ ! -f "${CACHE_DIR}/artifact-index.yaml" ]; then
    echo "artifact-index.yaml not found in cache: ${CACHE_DIR}" >&2
    return 1
  fi
  return 0
}

run_download_only_flow() {
  if ! init_offline_builder_context; then
    exit 1
  fi
  if ! run_download_only_prepare; then
    exit 1
  fi
  print_download_only_complete
  exit 0
}

run_build_offline_bundle_flow() {
  export OFFLINE_DEPLOYMENT INSTALL_SCRIPT_PATH="${SCRIPT_DIR}/install.sh"
  if ! init_offline_builder_context; then
    exit 1
  fi
  if ! load_offline_bundle_helpers; then
    exit 1
  fi

  printf '\n%s\n\n' "$(apex_ui_c 33 "$(apex_i18n build_offline_bundle_phase_prepare)")"
  if ! run_download_only_prepare; then
    exit 1
  fi

  printf '\n%s\n\n' "$(apex_ui_c 33 "$(apex_i18n build_offline_bundle_phase_pack)")"
  apex_offline_pack_bundle "$APEX_HOME" "$CACHE_DIR" "$OFFLINE_DEPLOYMENT" "$OUTPUT_PATH"
  exit $?
}

if [ "$OFFLINE_INSTALL" = "1" ]; then
  run_offline_install_flow
fi

if [ "$DOWNLOAD_ONLY" = "1" ]; then
  run_download_only_flow
fi

if [ "$BUILD_OFFLINE_BUNDLE" = "1" ]; then
  run_build_offline_bundle_flow
fi

if [ "$PACK_OFFLINE" = "1" ]; then
  run_pack_offline_flow
fi

if ! install_reject_unsupported_apex_host "$INSTALL_MODE"; then
  exit 1
fi

if ! install_require_tar; then
  exit 1
fi

case "$INSTALL_MODE" in
  apex|docker)
    if ! install_require_port_check_tool; then
      exit 1
    fi
    ;;
esac

if ! bootstrap_release_package; then
  echo "failed to bootstrap release package from $(resolve_install_package_base_url)" >&2
  echo "deploy-scripts are included inside the platform release archive, not downloaded separately." >&2
  echo "If you pipe curl to bash, export APEX_BASE_URL before bash, not before curl:" >&2
  echo "  curl -fsSL .../install.sh | APEX_BASE_URL=... bash -s -- -m apex" >&2
  exit 1
fi
trap cleanup_bootstrap_dir EXIT
trap 'on_install_interrupt 130' INT
trap 'on_install_interrupt 143' TERM

if ! load_apex_common; then
  echo "failed to load apex-common.sh from release package" >&2
  exit 1
fi

if ! apex_require_root_for_install_mode "$INSTALL_MODE"; then
  exit 1
fi

unset APEX_PORT_CONFLICT_ACK

if [ "$INSTALL_MODE" = "apex" ]; then
  if ! apex_resolve_deploy_profile; then
    exit 1
  fi
  if ! apex_require_host_for_deploy apex "$PRODUCT"; then
    exit 1
  fi
  if ! apex_assert_deploy_ports_ready "$PRODUCT" "$APEX_DEPLOY_PROFILE_LABEL"; then
    exit 1
  fi
elif [ "$INSTALL_MODE" = "docker" ]; then
  if ! apex_require_host_for_deploy docker all-in-one; then
    exit 1
  fi
  if ! apex_assert_deploy_ports_ready all-in-one "$APEX_PROFILE_ALL_IN_ONE"; then
    exit 1
  fi
fi

if [ "$INSTALL_MODE" = "docker" ]; then
  APEX_TELEMETRY_DEPLOYMENT_NAME="$APEX_PROFILE_ALL_IN_ONE"
else
  APEX_TELEMETRY_DEPLOYMENT_NAME="$APEX_DEPLOY_PROFILE_LABEL"
fi
export APEX_TELEMETRY_DEPLOYMENT_NAME

if ! load_install_ui; then
  apex_ui_init() { :; }
  apex_ui_box_open() { printf '\n%s\n\n' "=== $1 ==="; }
  apex_ui_box_line() { printf '  %s\n' "$1"; }
  apex_ui_box_blank() { printf '\n'; }
  apex_ui_box_heading() { printf '  %s\n' "$1"; }
  apex_ui_box_step() { printf '  %s  %s\n' "$1" "$2"; }
  apex_ui_box_kv() { printf '  %-12s %s\n' "$1" "$2"; }
  apex_ui_box_url() { printf '  %-12s %s\n' "$1" "$2"; }
  apex_ui_box_close() { printf '\n'; }
  apex_ui_section() { printf '\n%s\n\n' "$1"; }
  apex_ui_success() { apex_ui_section "$1"; }
  apex_ui_note() { printf '  %s\n' "$1"; }
  apex_ui_init
fi

print_welcome_banner() {
  local profile_label with_tdmodel
  case "$INSTALL_MODE" in
    apex)
      profile_label="${APEX_DEPLOY_PROFILE_LABEL:-$APEX_PROFILE_ALL_IN_ONE}"
      apex_ui_box_open "$(apex_i18n installer_title)" "36"
      apex_ui_box_blank
      apex_ui_box_line "$(apex_i18n installer_intro)"
      apex_ui_box_blank
      apex_ui_box_step "$(apex_i18n step_tag 1 2)" "$(apex_i18n step1_apex)"
      apex_ui_box_step "$(apex_i18n step_tag 2 2)" "$(apex_i18n step2_apex)"
      apex_ui_box_blank
      if [ "${PRODUCT:-}" = "all-in-one" ]; then
        if install_host_supports_tdmodel; then
          apex_ui_box_wrap "$(apex_format_allinone_welcome_line 1)"
        else
          apex_ui_box_wrap "$(apex_format_allinone_welcome_line 0)"
        fi
      elif [ "$PRODUCT" = "idmp" ]; then
        apex_ui_box_line "$(apex_i18n profile_selected "$profile_label")"
        apex_ui_box_line "$(apex_i18n idmp_endpoint_hint)"
        apex_ui_box_wrap "$(apex_i18n idmp_endpoint_hint2)"
      else
        apex_ui_box_line "$(apex_i18n profile_selected "$profile_label")"
      fi
      apex_ui_box_blank
      apex_ui_box_wrap "$(apex_i18n deploy_flow_note)"
      apex_ui_box_close
      ;;
    docker)
      apex_ui_box_open "$(apex_i18n docker_installer_title)" "36"
      apex_ui_box_blank
      apex_ui_box_line "$(apex_i18n installer_intro)"
      apex_ui_box_blank
      apex_ui_box_step "$(apex_i18n step_tag 1 2)" "$(apex_i18n step1_docker)"
      apex_ui_box_step "$(apex_i18n step_tag 2 2)" "$(apex_i18n step2_docker)"
      apex_ui_box_blank
      apex_ui_box_wrap "$(apex_i18n docker_flow_note)"
      apex_ui_box_close
      ;;
  esac
}

print_welcome_banner

if [ -z "${APEX_HOME:-}" ]; then
  APEX_HOME="${HOME}/.apex"
  if [ -r /dev/tty ] && [ -w /dev/tty ]; then
    printf "$(apex_i18n apex_home_prompt "$APEX_HOME")" > /dev/tty
    read -r input < /dev/tty
    if [ -n "$input" ]; then
      APEX_HOME="$input"
    fi
  fi
fi
export APEX_HOME

# Emits the configuration this release wants as its defaults. Packaged defaults
# such as component_manifest_urls are carried over from the release package.
render_release_config() {
  local base_url="$1" packaged="${INSTALL_BOOTSTRAP_DIR}/config.yaml"

  printf 'apex_home: "%s"\n' "$APEX_HOME"
  printf 'install_mode: %s\n' "$INSTALL_MODE"
  printf 'telemetry_enabled: true\n'
  if [ -n "$base_url" ]; then
    printf 'base_url: %s\n' "$base_url"
  fi
  # Append packaged defaults that the installer does not manage itself.
  if [ -n "${INSTALL_BOOTSTRAP_DIR:-}" ] && [ -f "$packaged" ]; then
    awk '
      /^[^[:space:]#]/ {
        keep = ($0 !~ /^(apex_home|install_mode|telemetry_enabled|base_url):/)
      }
      keep { print }
    ' "$packaged"
  fi
}

# Writes config to $1, preserving an existing user file by diverting the release
# defaults to <file>.new instead of overwriting.
install_config_file() {
  local target="$1" content="$2"
  local destination="$target"

  if [ -f "$target" ]; then
    destination="${target}.new"
    # Command substitution strips trailing newlines on both sides, so this
    # compares the payload rather than incidental whitespace.
    if [ "$(cat "$target" 2>/dev/null)" = "$(printf '%s' "$content")" ]; then
      rm -f "$destination"
      return 0
    fi
  fi
  printf '%s' "$content" > "$destination"
  if [ "$destination" != "$target" ]; then
    apex_ui_note "$(apex_i18n config_preserved_note "$target" "$destination")"
  fi
}

write_config() {
  local base_url content
  mkdir -p "$APEX_HOME"
  base_url=$(apex_config_base_url_for_install || true)
  if [ -n "$base_url" ] && [ "$INSTALL_MODE" != "docker" ]; then
    apex_ui_note "$(apex_i18n lan_base_url_note "$base_url")"
  fi
  content=$(render_release_config "$base_url")
  content="${content}
"
  install_config_file "${APEX_HOME}/config.yaml" "$content"
  if [ "${HOME}/.apex" != "$APEX_HOME" ]; then
    mkdir -p "${HOME}/.apex"
    install_config_file "${HOME}/.apex/config.yaml" "$content"
  fi
}

# Replaces the manifests in APEX_HOME with the manifests from this release.
install_manifests() {
  local source="${INSTALL_BOOTSTRAP_DIR}/manifests" dest="${APEX_HOME}/manifests"

  [ -d "$source" ] || return 0
  rm -rf "$dest"
  mkdir -p "$dest"
  cp -R "${source}/." "$dest/"
}

install_deploy_scripts() {
  local dest="${APEX_HOME}/deploy-scripts"

  mkdir -p "$APEX_HOME"
  rm -rf "$dest"
  cp -R "${INSTALL_BOOTSTRAP_DIR}/deploy-scripts" "$dest"
  chmod_deploy_scripts "$dest"
}

setup_docker_home() {
  DOCKER_BASE_URL="${APEX_DOCKER_BASE_URL:-https://downloads.taosdata.com/apex/docker/v1.0.0}"
  mkdir -p "${APEX_HOME}/docker" || return $?
  echo "$(apex_i18n downloading_docker_assets "$DOCKER_BASE_URL")"
  curl -fsSL "${DOCKER_BASE_URL}/tdengine.sh" -o "${APEX_HOME}/docker/tdengine.sh" || return $?
  curl -fsSL "${DOCKER_BASE_URL}/docker-compose-tdengine.yml" -o "${APEX_HOME}/docker/docker-compose-tdengine.yml" || return $?
  curl -fsSL "${DOCKER_BASE_URL}/.env.example" -o "${APEX_HOME}/docker/.env.example" || return $?
  chmod +x "${APEX_HOME}/docker/tdengine.sh" || return $?
}

initialize_telemetry_run() {
  local apex_cli="$1" run_id exit_code attempt
  [ -n "${APEX_TELEMETRY_RUN_ID:-}" ] && return 0
  attempt=1
  while [ "$attempt" -le 3 ]; do
    if run_id=$(APEX_HOME="$APEX_HOME" "$apex_cli" telemetry new-run-id 2>/dev/null); then
      exit_code=0
    else
      exit_code=$?
    fi
    if [ "$exit_code" -eq 0 ] && [ -n "$run_id" ]; then
      APEX_TELEMETRY_RUN_ID="$run_id"
      export APEX_TELEMETRY_RUN_ID
      return 0
    fi
    if [ "$exit_code" -eq 0 ]; then
      printf 'Warning: Apex telemetry did not return a run ID; telemetry reports will be skipped\n' >&2
      return 0
    fi
    attempt=$((attempt + 1))
    if [ "$attempt" -le 3 ]; then
      sleep 1
    fi
  done
  printf 'Warning: unable to initialize Apex telemetry after 3 attempts (last exit %s); telemetry reports will be skipped\n' "$exit_code" >&2
  return 0
}

report_installer_telemetry() {
  local apex_cli="$1" install_type="$2" step="$3" status="$4" error_code="${5:-}" error_message="${6:-}" exit_code
  [ -n "${APEX_TELEMETRY_RUN_ID:-}" ] || return 0

  set -- telemetry report --install-type "$install_type" \
    --deployment-name "$APEX_TELEMETRY_DEPLOYMENT_NAME" --step "$step" --status "$status"
  if [ "$status" = "failed" ]; then
    set -- "$@" --error-code "$error_code" --error-message "$error_message"
  fi

  if APEX_HOME="$APEX_HOME" "$apex_cli" "$@" >/dev/null 2>&1; then
    return 0
  else
    exit_code=$?
  fi
  [ "${APEX_TELEMETRY_DEBUG:-0}" != "1" ] || printf 'Apex telemetry report failed for step %s (exit %s)\n' "$step" "$exit_code" >&2
  return 0
}

print_release_package_version() {
  local binary="${INSTALL_BOOTSTRAP_DIR}/apex-${PLATFORM_OS}-${PLATFORM_ARCH}"

  if [ ! -f "$binary" ]; then
    echo "release package missing expected binary: apex-${PLATFORM_OS}-${PLATFORM_ARCH}" >&2
    return 1
  fi
  chmod +x "$binary" 2>/dev/null || true
  "$binary" version
}

print_install_complete() {
  case "$INSTALL_MODE" in
    docker)
      apex_ui_box_open "$(apex_i18n step1_complete_docker)" "33"
      apex_ui_box_blank
      apex_ui_box_line "$(apex_i18n prepared_on_machine)"
      apex_ui_box_blank
      apex_ui_box_kv "$(apex_i18n label_apex_home)" "${APEX_HOME}" "90" "0"
      apex_ui_box_kv "$(apex_i18n label_apex_cli)" "${INSTALL_DIR}/apex" "90" "32"
      apex_ui_box_line "$(apex_i18n docker_assets_list)"
      apex_ui_box_close
      ;;
    *)
      apex_ui_box_open "$(apex_i18n step1_complete_apex)" "33"
      apex_ui_box_blank
      apex_ui_box_line "$(apex_i18n installed_on_machine)"
      apex_ui_box_blank
      apex_ui_box_kv "$(apex_i18n label_apex_cli)" "${INSTALL_DIR}/apex" "90" "32"
      apex_ui_box_kv "$(apex_i18n label_apex_home)" "${APEX_HOME}" "90" "0"
      apex_ui_box_line "$(apex_i18n apex_files_copied)"
      apex_ui_box_close
      ;;
  esac
}

run_deployment() {
  local deploy_script="${APEX_HOME}/deploy-scripts/linux/deploy.sh"
  apex_ui_section "$(apex_i18n step2_deploy_title)" "36"
  printf '\n'
  export APEX_INSTALL_MODE="${INSTALL_MODE}"
  case "$(uname -s 2>/dev/null || true)" in
    MINGW*|MSYS*|CYGWIN*)
      if [ -f "${APEX_HOME}/deploy-scripts/windows/deploy.ps1" ]; then
        exec powershell.exe -NoProfile -ExecutionPolicy Bypass -File \
          "${APEX_HOME}/deploy-scripts/windows/deploy.ps1"
      fi
      ;;
  esac
  if [ "${APEX_NONINTERACTIVE:-}" != "1" ] && [ ! -t 0 ] && [ -r /dev/tty ] && [ -w /dev/tty ]; then
    "$deploy_script" < /dev/tty
  else
    "$deploy_script"
  fi
}

print_install_failure_hints() {
  apex_print_install_failure_hints "${BASE_URL}" "${INSTALL_MODE}" "${APEX_HOME:-}" \
    "${APEX_HOME:-${HOME}/.apex}/deploy-scripts/linux/deploy.sh"
}

print_deploy_step_failure_hints() {
  local report
  report="${APEX_HOME:-${HOME}/.apex}/reports/deployment-report.txt"
  apex_print_deploy_failure_hints "${INSTALL_MODE:-apex}" "${APEX_HOME:-${HOME}/.apex}" \
    "${APEX_HOME:-${HOME}/.apex}/deploy-scripts/linux/deploy.sh" \
    "$report" 1
}

# APEX_TEST_BEGIN_ON_INSTALL_ERROR
on_install_error() {
  local exit_code=$?

  # `set -E` inherits ERR into command-substitution subshells. Those
  # substitutions are used by the installer for optional probes and UI text;
  # exiting their subshell does not stop the main installer, so reporting here
  # could emit a false step-0 failure followed by the real step-0 success.
  # Let the failure propagate to the parent shell, which will report it if it
  # is actually fatal. BASH_SUBSHELL is available in macOS Bash 3.2.
  if [ "${BASH_SUBSHELL:-0}" -gt 0 ]; then
    return "$exit_code"
  fi

  trap - ERR
  if [ "${INSTALL_PHASE:-1}" = "2" ]; then
    if [ -f "${APEX_HOME:-}/.deploy-failure-hints-shown" ]; then
      rm -f "${APEX_HOME}/.deploy-failure-hints-shown" 2>/dev/null || true
    else
      print_deploy_step_failure_hints
    fi
    exit "$exit_code"
  fi
  if [ "${INSTALLER_TELEMETRY_STEP0_REPORTED:-0}" != "1" ] && [ -x "${INSTALLER_TELEMETRY_CLI:-}" ]; then
    report_installer_telemetry "$INSTALLER_TELEMETRY_CLI" "${INSTALL_MODE:-apex}" 0 failed \
      "${INSTALLER_FAILURE_CODE:-installer_setup_failed}" "installer setup failed (exit code ${exit_code})"
  elif [ "${INSTALL_MODE:-apex}" = "docker" ] && [ "${INSTALLER_TELEMETRY_STEP1_REPORTED:-0}" != "1" ] && [ -x "${INSTALLER_TELEMETRY_CLI:-}" ]; then
    report_installer_telemetry "$INSTALLER_TELEMETRY_CLI" docker 1 failed \
      "${INSTALLER_FAILURE_CODE:-installer_setup_failed}" "installer failed after Docker assets downloaded (exit code ${exit_code})"
  fi
  print_install_failure_hints
  exit "$exit_code"
}
# APEX_TEST_END_ON_INSTALL_ERROR

INSTALL_PHASE=1
trap on_install_error ERR

if [ -n "${APEX_INSTALL_DIR:-}" ]; then
  INSTALL_DIR="$APEX_INSTALL_DIR"
elif [ -d /usr/local/bin ] && [ -w /usr/local/bin ]; then
  INSTALL_DIR="/usr/local/bin"
else
  INSTALL_DIR="${HOME}/.local/bin"
fi

binary="${INSTALL_BOOTSTRAP_DIR}/apex-${PLATFORM_OS}-${PLATFORM_ARCH}"
if [ ! -f "$binary" ]; then
  echo "release package missing expected binary: apex-${PLATFORM_OS}-${PLATFORM_ARCH}" >&2
  exit 1
fi
chmod +x "$binary" 2>/dev/null || true
INSTALLER_TELEMETRY_CLI="$binary"
INSTALLER_TELEMETRY_STEP0_REPORTED=0
INSTALLER_TELEMETRY_STEP1_REPORTED=0
INSTALLER_FAILURE_CODE=installer_setup_failed
initialize_telemetry_run "$INSTALLER_TELEMETRY_CLI"

# APEX_TEST_BEGIN_LINUX_DOCKER_INSTALL
if [ "$INSTALL_MODE" = "docker" ]; then
  mkdir -p "$INSTALL_DIR"
  if install -m 0755 "$binary" "${INSTALL_DIR}/apex"; then
    :
  else
    install_rc=$?
    report_installer_telemetry "$binary" docker 0 failed installer_setup_failed "failed to install Apex CLI to ${INSTALL_DIR}/apex"
    INSTALLER_TELEMETRY_STEP0_REPORTED=1
    trap - ERR
    print_install_failure_hints
    exit "$install_rc"
  fi
  INSTALLER_FAILURE_CODE=config_write_failed
  write_config
  INSTALLER_FAILURE_CODE=deploy_scripts_install_failed
  install_deploy_scripts
  telemetry_cli="${INSTALL_DIR}/apex"
  "$telemetry_cli" version >/dev/null 2>&1 || true
  INSTALLER_TELEMETRY_CLI="$telemetry_cli"
  export APEX_TELEMETRY_CLI="$telemetry_cli"
  report_installer_telemetry "$telemetry_cli" docker 0 success
  INSTALLER_TELEMETRY_STEP0_REPORTED=1
  if setup_docker_home; then
    :
  else
    setup_rc=$?
    report_installer_telemetry "$telemetry_cli" docker 1 failed docker_resource_download_failed "failed to download Docker deployment assets"
    INSTALLER_TELEMETRY_STEP1_REPORTED=1
    trap - ERR
    print_install_failure_hints
    exit "$setup_rc"
  fi
  echo "$(apex_i18n docker_assets_downloaded "$APEX_HOME")"
  echo "$(apex_i18n apex_installed_to "${INSTALL_DIR}/apex")"
  "$telemetry_cli" version
  print_install_complete
  report_installer_telemetry "$telemetry_cli" docker 1 success
  INSTALLER_TELEMETRY_STEP1_REPORTED=1
  INSTALL_PHASE=2
  run_deployment
  trap - ERR
  exit 0
fi
# APEX_TEST_END_LINUX_DOCKER_INSTALL

mkdir -p "$INSTALL_DIR"
if install -m 0755 "$binary" "${INSTALL_DIR}/apex"; then
  :
else
  install_rc=$?
  report_installer_telemetry "$binary" "$INSTALL_MODE" 0 failed installer_setup_failed "failed to install Apex CLI to ${INSTALL_DIR}/apex"
  INSTALLER_TELEMETRY_STEP0_REPORTED=1
  trap - ERR
  print_install_failure_hints
  exit "$install_rc"
fi
INSTALLER_TELEMETRY_CLI="${INSTALL_DIR}/apex"

INSTALLER_FAILURE_CODE=config_write_failed
write_config

if ! install_assert_safe_apex_home_path "$APEX_HOME"; then
  exit 1
fi
INSTALLER_FAILURE_CODE=manifests_install_failed
install_manifests
rm -rf "${APEX_HOME}/scripts" "${APEX_HOME}/deploy-scripts"
cp -R "${INSTALL_BOOTSTRAP_DIR}/scripts" "${APEX_HOME}/scripts"
INSTALLER_FAILURE_CODE=deploy_scripts_install_failed
install_deploy_scripts

echo "$(apex_i18n apex_installed_to "${INSTALL_DIR}/apex")"
echo "$(apex_i18n apex_data_installed "$APEX_HOME" "$INSTALL_MODE")"
"${INSTALL_DIR}/apex" version
report_installer_telemetry "${INSTALL_DIR}/apex" apex 0 success
INSTALLER_TELEMETRY_STEP0_REPORTED=1
print_install_complete
INSTALL_PHASE=2
run_deployment
trap - ERR
