#!/usr/bin/env bash
set -Eeuo pipefail

readonly CLIENT_VERSION="1.2.0"
readonly MINIMUM_SING_BOX_VERSION="1.13.0"
readonly CONTROL_ORIGIN="https://connect.worldai.loan"
readonly LEGACY_CONTROL_ORIGIN="https://vpn.worldai.loan:8443"
readonly CONFIG_DIR="/etc/worldai-connect"
readonly STATE_DIR="/var/lib/worldai-connect"
readonly CONFIG_FILE="${CONFIG_DIR}/config.json"
readonly URL_FILE="${CONFIG_DIR}/subscription-url"
readonly LEGACY_URL_FILE="${CONFIG_DIR}/legacy-subscription-url"
readonly TOKEN_FILE="${CONFIG_DIR}/profile-token"
readonly CLIENT_VERSION_FILE="${CONFIG_DIR}/client-version"
readonly SERVICE_NAME="worldai-connect.service"
readonly UPDATE_SERVICE="worldai-connect-update.service"
readonly UPDATE_TIMER="worldai-connect-update.timer"

MODE="install"
case "${1:-}" in
  "") ;;
  --upgrade) MODE="upgrade" ;;
  --print-version)
    printf '%s\n' "${CLIENT_VERSION}"
    exit 0
    ;;
  *)
    printf 'Unknown argument: %s\n' "$1" >&2
    exit 2
    ;;
esac

die() {
  printf 'Error: %s\n' "$*" >&2
  exit 1
}

normalize_subscription_url() {
  local input="$1"
  if [[ ${input} =~ ^https://connect\.worldai\.loan/linux/([A-Za-z0-9]{48})/sing-box\.json$ ]]; then
    PROFILE_TOKEN="${BASH_REMATCH[1]}"
    CANONICAL_SUBSCRIPTION_URL="${CONTROL_ORIGIN}/linux/${PROFILE_TOKEN}/sing-box.json"
    LEGACY_SUBSCRIPTION_URL=""
    return 0
  fi
  if [[ ${input} =~ ^https://vpn\.worldai\.loan:8443/linux/([A-Za-z0-9]{48})/sing-box\.json$ ]]; then
    PROFILE_TOKEN="${BASH_REMATCH[1]}"
    CANONICAL_SUBSCRIPTION_URL="${CONTROL_ORIGIN}/linux/${PROFILE_TOKEN}/sing-box.json"
    LEGACY_SUBSCRIPTION_URL="${LEGACY_CONTROL_ORIGIN}/linux/${PROFILE_TOKEN}/sing-box.json"
    return 0
  fi
  return 1
}

fetch_config_with_legacy_fallback() {
  local target="$1"
  local primary="$2"
  local legacy="$3"
  if curl -fsS --connect-timeout 10 --max-time 30 --retry 2 "${primary}" -o "${target}"; then
    return 0
  fi
  [[ -n ${legacy} ]] && curl -fsS --connect-timeout 10 --max-time 30 --retry 2 "${legacy}" -o "${target}"
}

[[ ${EUID} -eq 0 ]] || die "run this installer with sudo"
command -v systemctl >/dev/null 2>&1 || die "systemd is required"

[[ -r /etc/os-release ]] || die "cannot identify the Linux distribution"
# shellcheck disable=SC1091
source /etc/os-release
case "${ID:-}:${ID_LIKE:-}" in
  *debian*|*ubuntu*) ;;
  *) die "only Debian and Ubuntu are supported" ;;
esac

case "$(uname -m)" in
  x86_64|amd64|aarch64|arm64) ;;
  *) die "only x64 and arm64 are supported" ;;
esac

if [[ ${MODE} == "upgrade" ]]; then
  [[ -r ${URL_FILE} ]] || die "the existing subscription URL is missing"
  SUBSCRIPTION_URL="$(cat "${URL_FILE}")"
  EXISTING_LEGACY_URL="$(cat "${LEGACY_URL_FILE}" 2>/dev/null || true)"
else
  printf 'Paste the Linux configuration URL (input is hidden): '
  IFS= read -r -s SUBSCRIPTION_URL
  printf '\n'
fi
normalize_subscription_url "${SUBSCRIPTION_URL}" || die "invalid configuration URL"
if [[ -n ${EXISTING_LEGACY_URL:-} ]] \
  && [[ ${EXISTING_LEGACY_URL} =~ ^https://vpn\.worldai\.loan:8443/linux/[A-Za-z0-9]{48}/sing-box\.json$ ]]; then
  LEGACY_SUBSCRIPTION_URL="${EXISTING_LEGACY_URL}"
fi

TEMP_DIR="$(mktemp -d)"
trap 'rm -rf "${TEMP_DIR}"' EXIT
INITIAL_CONFIG="${TEMP_DIR}/config.json"

export DEBIAN_FRONTEND=noninteractive
apt_refreshed=false
ensure_apt_refreshed() {
  if [[ ${apt_refreshed} != true ]]; then
    apt-get update
    apt_refreshed=true
  fi
}

missing_dependency=false
for command_name in curl gpg jq ss flock sha256sum; do
  command -v "${command_name}" >/dev/null 2>&1 || missing_dependency=true
done
if [[ ${MODE} == "install" || ${missing_dependency} == true ]]; then
  ensure_apt_refreshed
  apt-get install -y ca-certificates curl gpg jq iproute2 util-linux coreutils
fi

if [[ ! -s /etc/apt/sources.list.d/sagernet.sources || ! -s /etc/apt/keyrings/sagernet.asc ]]; then
  ensure_apt_refreshed
  install -d -m 0755 /etc/apt/keyrings
  curl -fsSL https://sing-box.app/gpg.key -o "${TEMP_DIR}/sagernet.asc"
  install -m 0644 "${TEMP_DIR}/sagernet.asc" /etc/apt/keyrings/sagernet.asc
  cat > /etc/apt/sources.list.d/sagernet.sources <<'EOF'
Types: deb
URIs: https://deb.sagernet.org/
Suites: *
Components: *
Enabled: yes
Signed-By: /etc/apt/keyrings/sagernet.asc
EOF
  apt_refreshed=false
fi

SING_BOX_VERSION="$(sing-box version 2>/dev/null | awk '/sing-box version/{print $3; exit}' || true)"
if [[ -z ${SING_BOX_VERSION} ]] || ! dpkg --compare-versions "${SING_BOX_VERSION}" ge "${MINIMUM_SING_BOX_VERSION}"; then
  ensure_apt_refreshed
  if dpkg-query -W -f='${Status}' sing-box 2>/dev/null | grep -q 'install ok installed'; then
    apt-get install -y --only-upgrade sing-box
  else
    apt-get install -y sing-box
  fi
fi
SING_BOX_VERSION="$(sing-box version | awk '/sing-box version/{print $3; exit}')"
[[ -n ${SING_BOX_VERSION} ]] || die "cannot read the sing-box version"
dpkg --compare-versions "${SING_BOX_VERSION}" ge "${MINIMUM_SING_BOX_VERSION}" \
  || die "sing-box ${MINIMUM_SING_BOX_VERSION} or newer is required"

fetch_config_with_legacy_fallback "${INITIAL_CONFIG}" "${CANONICAL_SUBSCRIPTION_URL}" "${LEGACY_SUBSCRIPTION_URL}" \
  || die "cannot download the Linux configuration"
sing-box check -c "${INITIAL_CONFIG}" || die "the downloaded sing-box configuration is invalid"
LISTEN_ADDRESS="$(jq -er '.inbounds[] | select(.tag == "local-mixed") | .listen' "${INITIAL_CONFIG}")"
LISTEN_PORT="$(jq -er '.inbounds[] | select(.tag == "local-mixed") | .listen_port' "${INITIAL_CONFIG}")"
[[ ${LISTEN_ADDRESS} == "127.0.0.1" ]] || die "the proxy must listen on 127.0.0.1"
[[ ${LISTEN_PORT} =~ ^[0-9]+$ ]] || die "the configuration has no valid local port"
if ! systemctl is-active --quiet "${SERVICE_NAME}" \
  && ss -H -ltn "sport = :${LISTEN_PORT}" | grep -q .; then
  die "local port ${LISTEN_PORT} is already in use"
fi

cat > "${TEMP_DIR}/worldai-connect-update" <<'UPDATE_SCRIPT'
#!/usr/bin/env bash
set -Eeuo pipefail

readonly CONFIG_DIR="/etc/worldai-connect"
readonly STATE_DIR="/var/lib/worldai-connect"
readonly CONFIG_FILE="${CONFIG_DIR}/config.json"
readonly URL_FILE="${CONFIG_DIR}/subscription-url"
readonly LEGACY_URL_FILE="${CONFIG_DIR}/legacy-subscription-url"
readonly TOKEN_FILE="${CONFIG_DIR}/profile-token"
readonly CLIENT_VERSION_FILE="${CONFIG_DIR}/client-version"
readonly ETAG_FILE="${STATE_DIR}/config.etag"
readonly CONTROL_ORIGIN="https://connect.worldai.loan"
readonly LEGACY_CONTROL_ORIGIN="https://vpn.worldai.loan:8443"
readonly HEARTBEAT_URL="https://connect.worldai.loan/linux/api/heartbeat"
readonly LEGACY_HEARTBEAT_URL="https://vpn.worldai.loan:8443/linux/api/heartbeat"
RELEASE_MANIFEST_URLS=(
  "https://connect.worldai.loan/downloads/linux/latest.json"
  "https://vpn.worldai.loan:8443/downloads/linux/latest.json"
)
OFFICIAL_INSTALLER_URLS=(
  "https://connect.worldai.loan/downloads/worldai-linux-install.sh"
  "https://vpn.worldai.loan:8443/downloads/worldai-linux-install.sh"
)

COMPONENT_PATHS=(
  /etc/worldai-connect/config.json
  /etc/worldai-connect/subscription-url
  /etc/worldai-connect/legacy-subscription-url
  /etc/worldai-connect/profile-token
  /etc/worldai-connect/client-version
  /etc/profile.d/worldai-connect-proxy.sh
  /usr/local/libexec/worldai-connect-update
  /usr/local/sbin/worldai-connect-uninstall
  /etc/systemd/system/worldai-connect.service
  /etc/systemd/system/worldai-connect-update.service
  /etc/systemd/system/worldai-connect-update.timer
)

exec 9>/run/lock/worldai-connect-update.lock
flock -n 9 || exit 0

TEMP_DIR="$(mktemp -d)"
CANDIDATE="${TEMP_DIR}/config.json"
NEW_ETAG="${TEMP_DIR}/config.etag"
MANIFEST="${TEMP_DIR}/latest.json"
INSTALLER="${TEMP_DIR}/worldai-linux-install.sh"
BACKUP_ROOT="${TEMP_DIR}/component-backup"
SING_BOX_BACKUP_ROOT="${TEMP_DIR}/sing-box-backup"
SING_BOX_BINARY_BACKUP="${SING_BOX_BACKUP_ROOT}/sing-box"
SING_BOX_PACKAGE_BACKUP=""
SING_BOX_PACKAGE_VERSION=""
SING_BOX_WAS_PACKAGED=false
UPDATE_TRANSACTION_ACTIVE=false
SERVICE_WAS_ACTIVE=false
SERVICE_WAS_ENABLED=false
TIMER_WAS_ACTIVE=false
TIMER_WAS_ENABLED=false

finish() {
  status=$?
  trap - EXIT
  if [[ ${status} -ne 0 && ${UPDATE_TRANSACTION_ACTIVE} == true ]]; then
    set +e
    restore_update_state
    rollback_status=$?
    set -e
    if [[ ${rollback_status} -ne 0 ]]; then
      echo "WorldAI Connect rollback encountered an error; manual repair is required" >&2
    fi
  fi
  if systemctl is-active --quiet worldai-connect.service; then
    token="$(cat "${TOKEN_FILE}" 2>/dev/null || true)"
    if [[ ${token} =~ ^[A-Za-z0-9]{48}$ ]]; then
      curl -fsS --connect-timeout 5 --max-time 10 -X POST \
        -H "Authorization: Bearer ${token}" "${HEARTBEAT_URL}" \
        >/dev/null 2>&1 \
        || curl -fsS --connect-timeout 5 --max-time 10 -X POST \
          -H "Authorization: Bearer ${token}" "${LEGACY_HEARTBEAT_URL}" \
          >/dev/null 2>&1 || true
    fi
  fi
  rm -rf "${TEMP_DIR}"
  exit "${status}"
}
trap finish EXIT

is_allowed_subscription_url() {
  [[ $1 =~ ^https://connect\.worldai\.loan/linux/[A-Za-z0-9]{48}/sing-box\.json$ ]] \
    || [[ $1 =~ ^https://vpn\.worldai\.loan:8443/linux/[A-Za-z0-9]{48}/sing-box\.json$ ]]
}

is_allowed_installer_url() {
  local url
  for url in "${OFFICIAL_INSTALLER_URLS[@]}"; do
    [[ $1 == "${url}" ]] && return 0
  done
  return 1
}

download_config() {
  local url="$1"
  local output="$2"
  local etag_args=(--etag-save "${NEW_ETAG}")
  if [[ -s ${ETAG_FILE} ]]; then
    etag_args+=(--etag-compare "${ETAG_FILE}")
  fi
  curl --silent --show-error --connect-timeout 10 --max-time 30 --retry 2 \
    "${etag_args[@]}" --output "${output}" --write-out '%{http_code}' "${url}"
}

fetch_config_with_legacy_fallback() {
  local primary="$1"
  local legacy="$2"
  local http_code
  http_code="$(download_config "${primary}" "${CANDIDATE}")" && {
    printf '%s\n' "${http_code}"
    return 0
  }
  [[ -n ${legacy} ]] || return 1
  rm -f "${CANDIDATE}" "${NEW_ETAG}"
  download_config "${legacy}" "${CANDIDATE}"
}

backup_components() {
  rm -rf "${BACKUP_ROOT}"
  install -d -m 0700 "${BACKUP_ROOT}"
  for path in "${COMPONENT_PATHS[@]}"; do
    if [[ -e ${path} ]]; then
      cp -a --parents "${path}" "${BACKUP_ROOT}" || return 1
    fi
  done
}

restore_components() {
  local status=0
  for path in "${COMPONENT_PATHS[@]}"; do
    rm -f "${path}" || status=1
    if [[ -e ${BACKUP_ROOT}${path} ]]; then
      install -d -m 0755 "$(dirname "${path}")" || status=1
      cp -a "${BACKUP_ROOT}${path}" "${path}" || status=1
    fi
  done
  return "${status}"
}

restore_unit_state() {
  local unit="$1"
  local was_active="$2"
  local was_enabled="$3"
  local status=0

  if [[ ${was_enabled} == true ]]; then
    systemctl enable "${unit}" >/dev/null 2>&1 || status=1
  else
    systemctl disable "${unit}" >/dev/null 2>&1 || status=1
  fi
  if [[ ${was_active} == true ]]; then
    systemctl restart "${unit}" >/dev/null 2>&1 \
      || systemctl start "${unit}" >/dev/null 2>&1 \
      || status=1
    systemctl is-active --quiet "${unit}" || status=1
  else
    systemctl stop "${unit}" >/dev/null 2>&1 || status=1
  fi
  return "${status}"
}

record_runtime_state() {
  SERVICE_WAS_ACTIVE=false
  SERVICE_WAS_ENABLED=false
  TIMER_WAS_ACTIVE=false
  TIMER_WAS_ENABLED=false
  systemctl is-active --quiet worldai-connect.service && SERVICE_WAS_ACTIVE=true
  systemctl is-enabled --quiet worldai-connect.service 2>/dev/null && SERVICE_WAS_ENABLED=true
  systemctl is-active --quiet worldai-connect-update.timer && TIMER_WAS_ACTIVE=true
  systemctl is-enabled --quiet worldai-connect-update.timer 2>/dev/null && TIMER_WAS_ENABLED=true
}

backup_sing_box() {
  rm -rf "${SING_BOX_BACKUP_ROOT}"
  install -d -m 0700 "${SING_BOX_BACKUP_ROOT}" || return 1
  [[ -x /usr/bin/sing-box ]] || return 1
  cp -a /usr/bin/sing-box "${SING_BOX_BINARY_BACKUP}" || return 1

  SING_BOX_WAS_PACKAGED=false
  SING_BOX_PACKAGE_VERSION=""
  SING_BOX_PACKAGE_BACKUP=""
  if dpkg-query -W -f='${Status}' sing-box 2>/dev/null | grep -q 'install ok installed'; then
    SING_BOX_WAS_PACKAGED=true
    SING_BOX_PACKAGE_VERSION="$(dpkg-query -W -f='${Version}' sing-box)" || return 1
    (
      cd "${SING_BOX_BACKUP_ROOT}"
      apt-get download "sing-box=${SING_BOX_PACKAGE_VERSION}"
    ) || return 1
    SING_BOX_PACKAGE_BACKUP="$(
      find "${SING_BOX_BACKUP_ROOT}" -maxdepth 1 -type f -name 'sing-box_*.deb' -print -quit
    )"
    [[ -n ${SING_BOX_PACKAGE_BACKUP} && -s ${SING_BOX_PACKAGE_BACKUP} ]] || return 1
  fi
}

restore_sing_box() {
  local status=0
  if [[ ${SING_BOX_WAS_PACKAGED} == true ]]; then
    [[ -n ${SING_BOX_PACKAGE_BACKUP} && -s ${SING_BOX_PACKAGE_BACKUP} ]] \
      || status=1
    if [[ ${status} -eq 0 ]]; then
      if ! dpkg -i "${SING_BOX_PACKAGE_BACKUP}" >/dev/null 2>&1; then
        apt-get install -y --allow-downgrades "${SING_BOX_PACKAGE_BACKUP}" \
          >/dev/null 2>&1 || status=1
      fi
      restored_version="$(dpkg-query -W -f='${Version}' sing-box 2>/dev/null || true)"
      [[ ${restored_version} == "${SING_BOX_PACKAGE_VERSION}" ]] || status=1
    fi
  elif dpkg-query -W -f='${Status}' sing-box 2>/dev/null | grep -q 'install ok installed'; then
    dpkg --purge sing-box >/dev/null 2>&1 || status=1
  fi
  if [[ -e ${SING_BOX_BINARY_BACKUP} ]]; then
    cp -a "${SING_BOX_BINARY_BACKUP}" /usr/bin/sing-box || status=1
  else
    status=1
  fi
  return "${status}"
}

backup_update_state() {
  record_runtime_state
  backup_components || return 1
  backup_sing_box || return 1
  UPDATE_TRANSACTION_ACTIVE=true
}

apply_original_runtime_state() {
  local status=0
  systemctl daemon-reload || status=1
  restore_unit_state worldai-connect.service "${SERVICE_WAS_ACTIVE}" "${SERVICE_WAS_ENABLED}" \
    || status=1
  restore_unit_state worldai-connect-update.timer "${TIMER_WAS_ACTIVE}" "${TIMER_WAS_ENABLED}" \
    || status=1
  return "${status}"
}

restore_update_state() {
  local status=0
  restore_components || status=1
  restore_sing_box || status=1
  systemctl daemon-reload || status=1
  restore_unit_state worldai-connect.service "${SERVICE_WAS_ACTIVE}" "${SERVICE_WAS_ENABLED}" \
    || status=1
  restore_unit_state worldai-connect-update.timer "${TIMER_WAS_ACTIVE}" "${TIMER_WAS_ENABLED}" \
    || status=1
  UPDATE_TRANSACTION_ACTIVE=false
  return "${status}"
}

ensure_minimum_sing_box() {
  minimum_version="$1"
  current_version="$(sing-box version 2>/dev/null | awk '/sing-box version/{print $3; exit}' || true)"
  if [[ -n ${current_version} ]] && dpkg --compare-versions "${current_version}" ge "${minimum_version}"; then
    return 0
  fi

  apt-get update || return 1
  if dpkg-query -W -f='${Status}' sing-box 2>/dev/null | grep -q 'install ok installed'; then
    apt-get install -y --only-upgrade sing-box || return 1
  else
    apt-get install -y sing-box || return 1
  fi
  current_version="$(sing-box version | awk '/sing-box version/{print $3; exit}')" || return 1
  dpkg --compare-versions "${current_version}" ge "${minimum_version}" || return 1
}

update_config() {
  subscription_url="$(cat "${URL_FILE}")"
  legacy_subscription_url="$(cat "${LEGACY_URL_FILE}" 2>/dev/null || true)"
  is_allowed_subscription_url "${subscription_url}" \
    || { echo "invalid configuration URL" >&2; return 1; }
  [[ -z ${legacy_subscription_url} ]] || is_allowed_subscription_url "${legacy_subscription_url}" \
    || { echo "invalid legacy configuration URL" >&2; return 1; }

  http_code="$(fetch_config_with_legacy_fallback "${subscription_url}" "${legacy_subscription_url}")" \
    || { echo "configuration check failed" >&2; return 1; }

  if [[ ${http_code} == "304" ]]; then
    return 0
  fi
  [[ ${http_code} == "200" ]] || { echo "configuration service returned HTTP ${http_code}" >&2; return 1; }
  sing-box check -c "${CANDIDATE}" || { echo "new configuration validation failed" >&2; return 1; }

  if [[ -f ${CONFIG_FILE} ]] && cmp -s "${CANDIDATE}" "${CONFIG_FILE}"; then
    [[ -s ${NEW_ETAG} ]] && install -m 0600 "${NEW_ETAG}" "${ETAG_FILE}"
    return 0
  fi

  config_backup="${STATE_DIR}/config.backup.json"
  if [[ -f ${CONFIG_FILE} ]]; then
    install -m 0640 -o root -g worldai-connect "${CONFIG_FILE}" "${config_backup}"
  fi
  install -m 0640 -o root -g worldai-connect "${CANDIDATE}" "${CONFIG_FILE}"
  restart_ok=true
  systemctl restart worldai-connect.service || restart_ok=false
  sleep 1
  if [[ ${restart_ok} != true ]] || ! systemctl is-active --quiet worldai-connect.service; then
    if [[ -f ${config_backup} ]]; then
      install -m 0640 -o root -g worldai-connect "${config_backup}" "${CONFIG_FILE}"
      systemctl restart worldai-connect.service || true
    fi
    echo "new configuration failed; restored the previous configuration" >&2
    return 1
  fi
  [[ -s ${NEW_ETAG} ]] && install -m 0600 "${NEW_ETAG}" "${ETAG_FILE}"
}

update_components() {
  manifest_downloaded=false
  for manifest_url in "${RELEASE_MANIFEST_URLS[@]}"; do
    if curl -fsS --connect-timeout 10 --max-time 30 --retry 2 \
      "${manifest_url}" -o "${MANIFEST}"; then
      manifest_downloaded=true
      break
    fi
  done
  [[ ${manifest_downloaded} == true ]] || { echo "client release check failed" >&2; return 1; }
  jq -e '
    (.schemaVersion == 1 or .schemaVersion == 2)
    and (.clientVersion | type == "string" and test("^[0-9]+\\.[0-9]+\\.[0-9]+$"))
    and (.minimumSingBoxVersion | type == "string" and test("^[0-9]+\\.[0-9]+\\.[0-9]+$"))
    and (.installer.size | type == "number" and . > 0 and floor == .)
    and (.installer.sha256 | type == "string" and test("^[0-9a-f]{64}$"))
  ' "${MANIFEST}" >/dev/null || { echo "invalid client release manifest" >&2; return 1; }

  release_version="$(jq -er '.clientVersion' "${MANIFEST}")"
  minimum_sing_box="$(jq -er '.minimumSingBoxVersion' "${MANIFEST}")"
  installer_url="$(jq -er '.installer.url' "${MANIFEST}")"
  installer_size="$(jq -er '.installer.size' "${MANIFEST}")"
  installer_sha256="$(jq -er '.installer.sha256' "${MANIFEST}")"
  is_allowed_installer_url "${installer_url}" \
    || { echo "client installer URL is not trusted" >&2; return 1; }

  current_version="$(cat "${CLIENT_VERSION_FILE}" 2>/dev/null || printf '0.0.0')"
  [[ ${current_version} =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || current_version="0.0.0"
  current_sing_box="$(sing-box version 2>/dev/null | awk '/sing-box version/{print $3; exit}' || true)"
  client_upgrade_needed=false
  sing_box_upgrade_needed=false
  dpkg --compare-versions "${release_version}" gt "${current_version}" \
    && client_upgrade_needed=true
  if [[ -z ${current_sing_box} ]] \
    || ! dpkg --compare-versions "${current_sing_box}" ge "${minimum_sing_box}"; then
    sing_box_upgrade_needed=true
  fi
  if [[ ${client_upgrade_needed} != true && ${sing_box_upgrade_needed} != true ]]; then
    return 0
  fi

  if [[ ${client_upgrade_needed} == true ]]; then
    curl -fsS --connect-timeout 10 --max-time 60 --retry 2 \
      "${installer_url}" -o "${INSTALLER}" \
      || { echo "client installer download failed" >&2; return 1; }
    [[ $(stat -c %s "${INSTALLER}") == "${installer_size}" ]] \
      || { echo "client installer size mismatch" >&2; return 1; }
    printf '%s  %s\n' "${installer_sha256}" "${INSTALLER}" | sha256sum -c - >/dev/null \
      || { echo "client installer hash mismatch" >&2; return 1; }
    bash -n "${INSTALLER}" || { echo "client installer syntax check failed" >&2; return 1; }
    [[ $(bash "${INSTALLER}" --print-version) == "${release_version}" ]] \
      || { echo "client installer version mismatch" >&2; return 1; }
  fi

  backup_update_state \
    || { echo "cannot create a complete update backup; no files were changed" >&2; return 1; }
  ensure_minimum_sing_box "${minimum_sing_box}" \
    || { echo "sing-box upgrade failed" >&2; return 1; }

  if [[ ${client_upgrade_needed} == true ]] && ! bash "${INSTALLER}" --upgrade; then
    echo "client upgrade failed; rollback scheduled" >&2
    return 1
  fi
  if [[ ${client_upgrade_needed} == true ]] \
    && [[ $(cat "${CLIENT_VERSION_FILE}" 2>/dev/null || true) != "${release_version}" ]]; then
    echo "client upgrade version verification failed; rollback scheduled" >&2
    return 1
  fi
  sing-box check -c "${CONFIG_FILE}" \
    || { echo "updated sing-box rejected the active configuration; rollback scheduled" >&2; return 1; }
  apply_original_runtime_state \
    || { echo "updated service state verification failed; rollback scheduled" >&2; return 1; }

  UPDATE_TRANSACTION_ACTIVE=false
  rm -rf "${BACKUP_ROOT}" "${SING_BOX_BACKUP_ROOT}"
  if [[ ${client_upgrade_needed} == true ]]; then
    printf 'WorldAI Connect upgraded from %s to %s\n' "${current_version}" "${release_version}"
  else
    printf 'WorldAI Connect sing-box requirement updated to %s\n' "${minimum_sing_box}"
  fi
}

status=0
update_config || status=1
update_components || status=1
exit "${status}"
UPDATE_SCRIPT

cat > "${TEMP_DIR}/worldai-connect-uninstall" <<'UNINSTALL_SCRIPT'
#!/usr/bin/env bash
set -Eeuo pipefail
[[ ${EUID} -eq 0 ]] || { echo "run this command with sudo" >&2; exit 1; }
systemctl disable --now worldai-connect-update.timer worldai-connect.service 2>/dev/null || true
rm -f /etc/systemd/system/worldai-connect.service \
  /etc/systemd/system/worldai-connect-update.service \
  /etc/systemd/system/worldai-connect-update.timer \
  /usr/local/libexec/worldai-connect-update \
  /etc/profile.d/worldai-connect-proxy.sh \
  /usr/local/sbin/worldai-connect-uninstall
rm -rf /etc/worldai-connect /var/lib/worldai-connect
systemctl daemon-reload
id worldai-connect >/dev/null 2>&1 && userdel worldai-connect || true
getent group worldai-connect >/dev/null 2>&1 && groupdel worldai-connect || true
echo "WorldAI Connect Linux service removed; sing-box was left installed."
UNINSTALL_SCRIPT

cat > "${TEMP_DIR}/worldai-connect.service" <<'SERVICE_UNIT'
[Unit]
Description=WorldAI Connect selective website proxy
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=worldai-connect
Group=worldai-connect
ExecStart=/usr/bin/sing-box run -c /etc/worldai-connect/config.json
Restart=on-failure
RestartSec=3s
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_NETLINK
LockPersonality=true

[Install]
WantedBy=multi-user.target
SERVICE_UNIT

cat > "${TEMP_DIR}/worldai-connect-update.service" <<'UPDATE_UNIT'
[Unit]
Description=Update WorldAI Connect client and selective proxy config
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/libexec/worldai-connect-update
Nice=10
NoNewPrivileges=true
PrivateTmp=true
UMask=0077
TimeoutStartSec=10min
UPDATE_UNIT

cat > "${TEMP_DIR}/worldai-connect-update.timer" <<'TIMER_UNIT'
[Unit]
Description=Check WorldAI Connect updates every five minutes

[Timer]
OnBootSec=1min
OnUnitActiveSec=5min
RandomizedDelaySec=30s
Persistent=true

[Install]
WantedBy=timers.target
TIMER_UNIT

cat > "${TEMP_DIR}/worldai-connect-proxy.sh" <<EOF
# WorldAI Connect local selective proxy for interactive login shells.
export HTTP_PROXY="http://127.0.0.1:${LISTEN_PORT}"
export HTTPS_PROXY="http://127.0.0.1:${LISTEN_PORT}"
export ALL_PROXY="socks5h://127.0.0.1:${LISTEN_PORT}"
export http_proxy="\${HTTP_PROXY}"
export https_proxy="\${HTTPS_PROXY}"
export all_proxy="\${ALL_PROXY}"
export NO_PROXY="localhost,127.0.0.1,::1"
export no_proxy="\${NO_PROXY}"
EOF

getent group worldai-connect >/dev/null 2>&1 || groupadd --system worldai-connect
id worldai-connect >/dev/null 2>&1 || useradd \
  --system --gid worldai-connect --home-dir "${STATE_DIR}" \
  --shell /usr/sbin/nologin worldai-connect
install -d -m 0750 -o root -g worldai-connect "${CONFIG_DIR}"
install -d -m 0750 -o worldai-connect -g worldai-connect "${STATE_DIR}"
install -d -m 0755 /usr/local/libexec /usr/local/sbin

OLD_CONFIG="${TEMP_DIR}/old-config.json"
if [[ ${MODE} == "upgrade" && -f ${CONFIG_FILE} ]]; then
  cp -a "${CONFIG_FILE}" "${OLD_CONFIG}"
fi
install -m 0640 -o root -g worldai-connect "${INITIAL_CONFIG}" "${CONFIG_FILE}"
printf '%s\n' "${CANONICAL_SUBSCRIPTION_URL}" > "${URL_FILE}"
if [[ -n ${LEGACY_SUBSCRIPTION_URL} ]]; then
  printf '%s\n' "${LEGACY_SUBSCRIPTION_URL}" > "${LEGACY_URL_FILE}"
else
  rm -f "${LEGACY_URL_FILE}"
fi
printf '%s\n' "${PROFILE_TOKEN}" > "${TOKEN_FILE}"
chmod 0600 "${URL_FILE}" "${TOKEN_FILE}"
[[ ! -e ${LEGACY_URL_FILE} ]] || chmod 0600 "${LEGACY_URL_FILE}"
install -m 0755 "${TEMP_DIR}/worldai-connect-update" /usr/local/libexec/worldai-connect-update
install -m 0755 "${TEMP_DIR}/worldai-connect-uninstall" /usr/local/sbin/worldai-connect-uninstall
install -m 0644 "${TEMP_DIR}/worldai-connect.service" /etc/systemd/system/worldai-connect.service
install -m 0644 "${TEMP_DIR}/worldai-connect-update.service" /etc/systemd/system/worldai-connect-update.service
install -m 0644 "${TEMP_DIR}/worldai-connect-update.timer" /etc/systemd/system/worldai-connect-update.timer
install -m 0644 "${TEMP_DIR}/worldai-connect-proxy.sh" /etc/profile.d/worldai-connect-proxy.sh

systemctl daemon-reload
systemctl enable "${SERVICE_NAME}" >/dev/null
restart_ok=true
systemctl restart "${SERVICE_NAME}" || restart_ok=false
sleep 1
if [[ ${restart_ok} != true ]] || ! systemctl is-active --quiet "${SERVICE_NAME}"; then
  if [[ -f ${OLD_CONFIG} ]]; then
    install -m 0640 -o root -g worldai-connect "${OLD_CONFIG}" "${CONFIG_FILE}"
    systemctl restart "${SERVICE_NAME}" || true
  fi
  die "the background service failed to remain active"
fi
printf '%s\n' "${CLIENT_VERSION}" > "${CLIENT_VERSION_FILE}"
chmod 0600 "${CLIENT_VERSION_FILE}"
systemctl enable --now "${UPDATE_TIMER}" >/dev/null
if [[ ${MODE} == "install" ]]; then
  systemctl start "${UPDATE_SERVICE}" || true
fi

printf '\nWorldAI Connect Linux %s installed.\n' "${CLIENT_VERSION}"
printf 'Local HTTP proxy: http://127.0.0.1:%s\n' "${LISTEN_PORT}"
printf 'Local SOCKS proxy: socks5h://127.0.0.1:%s\n' "${LISTEN_PORT}"
printf 'Logs: journalctl -u worldai-connect -e\n'
printf 'Uninstall: sudo worldai-connect-uninstall\n'
