#!/usr/bin/env bash
# Clavue one-line installer (x.ai-style).
#
#   curl -fsSL https://www.clavue.com/cli/install.sh | bash
#   curl -fsSL https://www.clavue.com/install.sh | bash
#   curl -fsSL https://www.clavue.com/cli/install.sh | bash -s -- 11.0.6
#
# Env:
#   CLAVUE_PACKAGE   npm package (default: iclavue)
#   CLAVUE_VERSION   version or "latest" (default: latest)
#   CLAVUE_NPM_FLAGS extra flags for npm install -g
#
set -euo pipefail

PACKAGE="${CLAVUE_PACKAGE:-iclavue}"
VERSION_INPUT="${1:-${CLAVUE_VERSION:-latest}}"
# Product CLI requires Node 22+ (better-sqlite3@13 has no deprecated prebuild-install).
MIN_NODE_MAJOR=22

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

print_banner() {
  printf '\n'
  printf '  龍  CLAVUE  —  execution-first coding CLI\n'
  printf '  Installer: npm package %s\n' "$PACKAGE"
  printf '\n'
}

check_node() {
  if ! command -v node >/dev/null 2>&1; then
    printf 'Node.js %s+ is required but not found.\n' "$MIN_NODE_MAJOR" >&2
    printf 'Install Node, then re-run this script:\n' >&2
    printf '  macOS:  brew install node\n' >&2
    printf '  nvm:    curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash\n' >&2
    printf '          nvm install %s\n' "$MIN_NODE_MAJOR" >&2
    printf '  https://nodejs.org/\n' >&2
    exit 1
  fi

  local node_major
  node_major="$(node -p "process.versions.node.split('.')[0]" 2>/dev/null || true)"
  if [[ -z "$node_major" || "$node_major" -lt "$MIN_NODE_MAJOR" ]]; then
    printf 'clavue requires Node.js %s or newer. Found: %s\n' \
      "$MIN_NODE_MAJOR" "$(node -v 2>/dev/null || echo unknown)" >&2
    printf 'Upgrade Node, then re-run:\n' >&2
    printf '  nvm install %s && nvm use %s\n' "$MIN_NODE_MAJOR" "$MIN_NODE_MAJOR" >&2
    printf '  # or: brew install node\n' >&2
    exit 1
  fi
}

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

# npm global install fails with ENOTEMPTY when a prior install left staging dirs.
clean_global_residue() {
  local remove_live_package="${1:-0}"
  local prefix
  prefix="$(npm prefix -g 2>/dev/null || true)"
  if [[ -z "$prefix" ]]; then
    return 0
  fi

  local node_modules="${prefix}/lib/node_modules"
  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 bin_link="${prefix}/bin/${PACKAGE}"
  local needs_sudo=0
  local has_residue=0
  if [[ "$remove_live_package" -eq 1 && -e "$pkg_dir" ]]; then
    has_residue=1
  fi
  if [[ -n "$(compgen -G "${node_modules}/.${PACKAGE}-*" || true)" ]]; then
    has_residue=1
  fi
  if [[ -L "$bin_link" && ! -e "$bin_link" ]]; then
    has_residue=1
  fi
  if [[ "$has_residue" -eq 0 ]]; then
    return 0
  fi
  if [[ ! -w "$node_modules" ]]; then
    needs_sudo=1
  fi

  printf 'Cleaning leftover %s install in %s...\n' "$PACKAGE" "$node_modules"
  local live_target=()
  if [[ "$remove_live_package" -eq 1 ]]; then
    live_target=("$pkg_dir")
  fi
  if [[ "$needs_sudo" -eq 1 ]]; then
    sudo rm -rf "${live_target[@]}" "${node_modules}"/."${PACKAGE}"-* 2>/dev/null || true
    if [[ -L "$bin_link" && ! -e "$bin_link" ]]; then
      sudo rm -f "$bin_link" 2>/dev/null || true
    fi
  else
    rm -rf "${live_target[@]}" "${node_modules}"/."${PACKAGE}"-* 2>/dev/null || true
    if [[ -L "$bin_link" && ! -e "$bin_link" ]]; then
      rm -f "$bin_link" 2>/dev/null || true
    fi
  fi
}

warn_alias_conflicts() {
  local name path
  local any=0
  printf 'Checking mindshare launch aliases...\n'
  for name in agent ai chat; do
    if command -v "$name" >/dev/null 2>&1; then
      path="$(command -v "$name" 2>/dev/null || true)"
      if [[ -n "$path" ]] && printf '%s' "$path" | grep -Eqi 'iclavue|clavue'; then
        printf '  · %s → %s  (Clavue — ok)\n' "$name" "$path"
        continue
      fi
      any=1
      printf '  ! %s already on PATH: %s\n' "$name" "${path:-?}"
      printf '    npm install will point this name at Clavue.\n'
    else
      printf '  · %s free — will install as Clavue alias\n' "$name"
    fi
  done
  if [[ "$any" -eq 1 ]]; then
    printf '\nAlias conflict (not fatal). Primary command: clavue\n\n'
  fi
}

# Run npm install; hide only the known-harmless upstream deprecation if any
# leftover appears. Real errors still surface (npm exits non-zero).
npm_install_global() {
  local spec="$1"
  # shellcheck disable=SC2086
  if npm install -g "$spec" ${CLAVUE_NPM_FLAGS:-} 2> >(
    # Filter only the prebuild-install deprecation line (legacy packages).
    grep -v -E 'npm warn deprecated prebuild-install@|prebuild-install@.*No longer maintained' >&2 || true
  ); then
    return 0
  fi
  return 1
}

main() {
  print_banner
  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 'One-shot without global install:  npx -y %s@%s\n' "$PACKAGE" "$version"
  warn_alias_conflicts
  clean_global_residue
  if ! npm_install_global "${PACKAGE}@${version}"; then
    printf '\nnpm install failed. Retrying after deeper cleanup...\n' >&2
    clean_global_residue 1
    npm_install_global "${PACKAGE}@${version}"
  fi

  printf '\nInstalled %s@%s\n' "$PACKAGE" "$version"
  printf 'Commands:\n'
  printf '  clavue   (primary)\n'
  printf '  agent · ai · chat  (aliases)\n'
  printf '  iclavue  (package name)\n'
  case "$(uname -s 2>/dev/null || echo unknown)" in
    MINGW*|MSYS*|CYGWIN*|Windows_NT)
      printf '\nWindows note:\n'
      printf '  · npm package does NOT include clavue-pager.exe (avoids 360 false positives)\n'
      printf '  · First interactive launch downloads UI into %%USERPROFILE%%\\.clavue\\native\\\n'
      printf '  · Skip download: set CLAVUE_SKIP_NATIVE_DOWNLOAD=1\n'
      ;;
  esac

  if command -v clavue >/dev/null 2>&1; then
    clavue --version || true
  elif command -v iclavue >/dev/null 2>&1; then
    iclavue --version || true
  else
    printf 'Warning: clavue not on PATH. Check: npm bin -g\n' >&2
  fi

  printf '\nNext:\n'
  printf '  clavue\n'
  printf '  First launch: set provider / API (or login Clavue Cloud).\n'
  printf '  Reopen setup: clavue provider\n'
  printf '  Docs: https://www.clavue.com\n'
  printf '\n'
}

main "$@"
