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

PACKAGE="${CLAVUE_PACKAGE:-clavue}"
VERSION_INPUT="${1:-${CLAVUE_VERSION:-latest}}"

need_cmd() {
  if ! command -v "$1" >/dev/null 2>&1; then
    printf 'Missing required command: %s\n' "$1" >&2
    exit 1
  fi
}

check_node() {
  need_cmd node

  local node_major
  node_major="$(node -p "process.versions.node.split('.')[0]")"
  if [[ -z "$node_major" || "$node_major" -lt 18 ]]; then
    printf 'clavue requires Node.js 18 or newer. Found: %s\n' "$(node -v)" >&2
    exit 1
  fi
}

resolve_version() {
  if [[ "$VERSION_INPUT" != "latest" ]]; then
    printf '%s' "${VERSION_INPUT#v}"
    return 0
  fi

  npm view "$PACKAGE" version
}

# npm's global install does an atomic rename of the existing package
# directory into a `.<name>-<rand>` staging directory before unpacking the
# new version. On macOS APFS this fails with ENOTEMPTY when the previous
# install left over files (interrupted install, leftover symlink target,
# leftover staging dir from a prior failed run). Clean leftovers first so
# the next `npm install -g` can rename without conflict.
clean_global_residue() {
  local prefix
  prefix="$(npm prefix -g 2>/dev/null || true)"
  if [[ -z "$prefix" ]]; then
    return 0
  fi

  local node_modules="${prefix}/lib/node_modules"
  # Linux/macOS layout uses lib/node_modules; some distros use just
  # node_modules under prefix. Try both.
  if [[ ! -d "$node_modules" ]]; then
    if [[ -d "${prefix}/node_modules" ]]; then
      node_modules="${prefix}/node_modules"
    else
      return 0
    fi
  fi

  local pkg_dir="${node_modules}/${PACKAGE}"
  local needs_sudo=0
  if [[ -e "$pkg_dir" || -n "$(compgen -G "${node_modules}/.${PACKAGE}-*" || true)" ]]; then
    if [[ ! -w "$node_modules" ]]; then
      needs_sudo=1
    fi
  else
    return 0
  fi

  printf 'Cleaning leftover %s install in %s...\n' "$PACKAGE" "$node_modules"
  if [[ "$needs_sudo" -eq 1 ]]; then
    sudo rm -rf "$pkg_dir" "${node_modules}"/."${PACKAGE}"-* 2>/dev/null || true
  else
    rm -rf "$pkg_dir" "${node_modules}"/."${PACKAGE}"-* 2>/dev/null || true
  fi
}

main() {
  need_cmd npm
  check_node

  local version
  version="$(resolve_version)"
  if [[ -z "$version" ]]; then
    printf 'Unable to determine the latest %s version from npm.\n' "$PACKAGE" >&2
    exit 1
  fi

  printf 'Installing %s@%s globally from npm...\n' "$PACKAGE" "$version"
  printf 'For one-shot use without a global install, run: npx -y %s@%s\n' "$PACKAGE" "$version"
  clean_global_residue
  if ! npm install -g "${PACKAGE}@${version}"; then
    printf '\nnpm install failed. Retrying once after a deeper cleanup...\n' >&2
    clean_global_residue
    npm install -g "${PACKAGE}@${version}"
  fi

  printf 'Installed %s@%s globally\n' "$PACKAGE" "$version"
  printf 'Available commands after npm install: clavue\n'
  clavue --version || true

  printf '\nNext step:\n'
  printf '  Run: clavue\n'
  printf '  First launch opens API setup. Choose "自定义 API 配置" to enter your API URL, key, and optional model slots.\n'
  printf '  You can reopen setup any time with: clavue provider\n'
}

main "$@"
