#!/usr/bin/env bash
# ──────────────────────────────────────────────────────────────────────────────
#  NEXUS AI CLI — Linux Installer
#  Usage:  curl -fsSL https://nexusai.run/install.sh | bash
#      or: bash install.sh
#      or: bash install.sh --api-url https://your-self-hosted.example.com
# ──────────────────────────────────────────────────────────────────────────────
set -euo pipefail
IFS=$'\n\t'

# ── Constants ─────────────────────────────────────────────────────────────────
CLI_NAME="nexusapp-cli"
CLI_CMD="nexus"
CLI_VERSION="2.0.0"
MIN_NODE_MAJOR=18
NODE_INSTALL_VERSION=20        # LTS version to install if Node is missing
DEFAULT_API_URL="https://nexusai.run"
RELEASE_URL="${DEFAULT_API_URL}/releases/cli/${CLI_NAME}-${CLI_VERSION}.tgz"
CONFIG_DIR="${HOME}/.nexusai"

# ── Colors ────────────────────────────────────────────────────────────────────
if [ -t 1 ] && command -v tput &>/dev/null && tput colors &>/dev/null; then
  RED=$(tput setaf 1); GREEN=$(tput setaf 2); YELLOW=$(tput setaf 3)
  BLUE=$(tput setaf 4); CYAN=$(tput setaf 6); BOLD=$(tput bold); RESET=$(tput sgr0)
else
  RED=''; GREEN=''; YELLOW=''; BLUE=''; CYAN=''; BOLD=''; RESET=''
fi

# ── Logging ───────────────────────────────────────────────────────────────────
step()    { echo "${BLUE}${BOLD}==> $*${RESET}"; }
info()    { echo "    $*"; }
success() { echo "${GREEN}${BOLD} ✓  $*${RESET}"; }
warn()    { echo "${YELLOW} ⚠  $*${RESET}"; }
error()   { echo "${RED}${BOLD} ✗  $*${RESET}" >&2; }
die()     { error "$*"; exit 1; }

# ── Banner ────────────────────────────────────────────────────────────────────
print_banner() {
  echo ""
  echo "${CYAN}${BOLD}  ███╗   ██╗███████╗██╗  ██╗██╗   ██╗███████╗     █████╗ ██╗${RESET}"
  echo "${CYAN}${BOLD}  ████╗  ██║██╔════╝╚██╗██╔╝██║   ██║██╔════╝    ██╔══██╗██║${RESET}"
  echo "${CYAN}${BOLD}  ██╔██╗ ██║█████╗   ╚███╔╝ ██║   ██║███████╗    ███████║██║${RESET}"
  echo "${CYAN}${BOLD}  ██║╚██╗██║██╔══╝   ██╔██╗ ██║   ██║╚════██║    ██╔══██║██║${RESET}"
  echo "${CYAN}${BOLD}  ██║ ╚████║███████╗██╔╝ ██╗╚██████╔╝███████║    ██║  ██║██║${RESET}"
  echo "${CYAN}${BOLD}  ╚═╝  ╚═══╝╚══════╝╚═╝  ╚═╝ ╚═════╝ ╚══════╝    ╚═╝  ╚═╝╚═╝${RESET}"
  echo ""
  echo "  ${BOLD}CLI Installer${RESET} — version ${CLI_VERSION}"
  echo "  ${BLUE}https://nexusai.run${RESET}"
  echo ""
}

# ── Parse arguments ───────────────────────────────────────────────────────────
API_URL="${NEXUSAI_API_URL:-${DEFAULT_API_URL}}"
SKIP_NODE_INSTALL=false
UNINSTALL=false

while [[ $# -gt 0 ]]; do
  case "$1" in
    --api-url)      API_URL="$2"; shift 2 ;;
    --skip-node)    SKIP_NODE_INSTALL=true; shift ;;
    --uninstall)    UNINSTALL=true; shift ;;
    --version|-v)   echo "${CLI_NAME} installer v${CLI_VERSION}"; exit 0 ;;
    --help|-h)
      echo "Usage: bash install.sh [OPTIONS]"
      echo ""
      echo "Options:"
      echo "  --api-url <url>   Set the NEXUS AI API URL (default: ${DEFAULT_API_URL})"
      echo "  --skip-node       Skip automatic Node.js installation"
      echo "  --uninstall       Remove NEXUS AI CLI from this machine"
      echo "  --version         Print installer version"
      echo "  --help            Show this help"
      exit 0 ;;
    *) die "Unknown option: $1. Run with --help for usage." ;;
  esac
done

# ── System checks ─────────────────────────────────────────────────────────────
check_os() {
  step "Checking system"
  if [[ "$(uname -s)" != "Linux" ]]; then
    die "This installer supports Linux only. For macOS use: brew install nexusai/tap/nexus"
  fi

  ARCH=$(uname -m)
  case "${ARCH}" in
    x86_64)           ARCH_LABEL="x86_64 (amd64)" ;;
    aarch64|arm64)    ARCH_LABEL="arm64" ;;
    armv7l)           ARCH_LABEL="armv7l" ;;
    *)                die "Unsupported architecture: ${ARCH}" ;;
  esac

  info "OS:   Linux"
  info "Arch: ${ARCH_LABEL}"

  # Detect distro
  if [ -f /etc/os-release ]; then
    # shellcheck source=/dev/null
    . /etc/os-release
    DISTRO="${ID:-unknown}"
    DISTRO_VERSION="${VERSION_ID:-}"
    info "Distro: ${PRETTY_NAME:-${DISTRO}}"
  elif [ -f /etc/alpine-release ]; then
    DISTRO="alpine"
    DISTRO_VERSION=$(cat /etc/alpine-release)
    info "Distro: Alpine Linux ${DISTRO_VERSION}"
  else
    DISTRO="unknown"
    warn "Could not detect Linux distribution. Proceeding anyway."
  fi
}

# ── sudo helper ───────────────────────────────────────────────────────────────
need_sudo() {
  if [[ $EUID -eq 0 ]]; then
    "$@"
  elif command -v sudo &>/dev/null; then
    sudo "$@"
  else
    die "This step requires root privileges. Please run as root or install sudo."
  fi
}

# ── Node.js installation ──────────────────────────────────────────────────────
check_node() {
  step "Checking Node.js"

  if command -v node &>/dev/null; then
    NODE_VERSION=$(node --version | sed 's/v//')
    NODE_MAJOR=$(echo "${NODE_VERSION}" | cut -d. -f1)
    if [[ "${NODE_MAJOR}" -ge "${MIN_NODE_MAJOR}" ]]; then
      success "Node.js ${NODE_VERSION} — OK (>= ${MIN_NODE_MAJOR} required)"
      return 0
    else
      warn "Node.js ${NODE_VERSION} is too old (need v${MIN_NODE_MAJOR}+)"
    fi
  else
    warn "Node.js not found"
  fi

  if [[ "${SKIP_NODE_INSTALL}" == "true" ]]; then
    die "Node.js v${MIN_NODE_MAJOR}+ is required. Install it manually and re-run this script."
  fi

  install_node
}

install_node() {
  step "Installing Node.js ${NODE_INSTALL_VERSION} LTS"

  case "${DISTRO}" in
    ubuntu|debian|linuxmint|pop|elementary|kali|raspbian)
      install_node_deb ;;
    rhel|centos|fedora|rocky|almalinux|amzn|ol)
      install_node_rpm ;;
    alpine)
      install_node_alpine ;;
    arch|manjaro|endeavouros)
      install_node_pacman ;;
    opensuse*|sles)
      install_node_zypper ;;
    *)
      install_node_nvm ;;  # Universal fallback
  esac

  # Verify
  NODE_VERSION=$(node --version 2>/dev/null | sed 's/v//') || die "Node.js installation failed."
  success "Node.js ${NODE_VERSION} installed"

  if ! command -v npm &>/dev/null; then
    die "npm was not installed alongside Node.js. Please install npm manually."
  fi
  success "npm $(npm --version) ready"
}

install_node_deb() {
  info "Installing via NodeSource (Debian/Ubuntu)"
  if ! command -v curl &>/dev/null; then
    need_sudo apt-get update -q
    need_sudo apt-get install -y -q curl
  fi
  curl -fsSL "https://deb.nodesource.com/setup_${NODE_INSTALL_VERSION}.x" | need_sudo bash -
  need_sudo apt-get install -y -q nodejs
}

install_node_rpm() {
  info "Installing via NodeSource (RHEL/CentOS/Fedora)"
  if ! command -v curl &>/dev/null; then
    if command -v dnf &>/dev/null; then
      need_sudo dnf install -y curl
    else
      need_sudo yum install -y curl
    fi
  fi
  curl -fsSL "https://rpm.nodesource.com/setup_${NODE_INSTALL_VERSION}.x" | need_sudo bash -
  if command -v dnf &>/dev/null; then
    need_sudo dnf install -y nodejs
  else
    need_sudo yum install -y nodejs
  fi
}

install_node_alpine() {
  info "Installing via apk (Alpine)"
  need_sudo apk add --update nodejs npm
}

install_node_pacman() {
  info "Installing via pacman (Arch)"
  need_sudo pacman -Sy --noconfirm nodejs npm
}

install_node_zypper() {
  info "Installing via zypper (openSUSE)"
  need_sudo zypper install -y nodejs npm
}

install_node_nvm() {
  warn "Unknown distro — installing Node.js via nvm"
  info "Installing nvm..."
  export NVM_DIR="${HOME}/.nvm"
  curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
  # shellcheck source=/dev/null
  [ -s "${NVM_DIR}/nvm.sh" ] && \. "${NVM_DIR}/nvm.sh"
  nvm install "${NODE_INSTALL_VERSION}"
  nvm use "${NODE_INSTALL_VERSION}"
  nvm alias default "${NODE_INSTALL_VERSION}"

  # Persist nvm in shell rc files
  for RC in "${HOME}/.bashrc" "${HOME}/.zshrc" "${HOME}/.profile"; do
    if [ -f "${RC}" ] && ! grep -q 'NVM_DIR' "${RC}"; then
      {
        echo ''
        echo '# nvm — added by NEXUS AI CLI installer'
        echo 'export NVM_DIR="$HOME/.nvm"'
        # shellcheck disable=SC2016
        echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"'
      } >> "${RC}"
    fi
  done
}

# ── CLI Installation ──────────────────────────────────────────────────────────
install_cli() {
  step "Installing ${CLI_NAME} v${CLI_VERSION}"

  # Determine if we need global npm permissions
  NPM_PREFIX=$(npm config get prefix 2>/dev/null || echo "/usr/local")
  NPM_BIN="${NPM_PREFIX}/bin"

  # Check if we can write to npm prefix without sudo
  if [ -w "${NPM_PREFIX}" ] || [[ $EUID -eq 0 ]]; then
    NPM_CMD="npm"
  else
    NPM_CMD="need_sudo npm"
  fi

  # Try to install from official release URL first
  info "Downloading from ${RELEASE_URL}"
  if ${NPM_CMD} install -g "${RELEASE_URL}" 2>/dev/null; then
    success "${CLI_CMD} installed from release"
  else
    # Fallback: try npm registry
    warn "Release download failed, trying npm registry…"
    if ${NPM_CMD} install -g "${CLI_NAME}@${CLI_VERSION}" 2>/dev/null; then
      success "${CLI_CMD} installed from npm registry"
    else
      die "Installation failed. Check your network connection and try again, or install manually:\n\n  npm install -g ${RELEASE_URL}"
    fi
  fi

  # Verify the binary is accessible
  if ! command -v "${CLI_CMD}" &>/dev/null; then
    # It may be installed but not in PATH — check common locations
    CANDIDATE=""
    for DIR in "${NPM_BIN}" "${HOME}/.local/bin" "${HOME}/.nvm/versions/node/$(node --version 2>/dev/null)/bin" "/usr/local/bin" "/usr/bin"; do
      if [ -x "${DIR}/${CLI_CMD}" ]; then
        CANDIDATE="${DIR}"
        break
      fi
    done

    if [ -n "${CANDIDATE}" ]; then
      warn "'${CLI_CMD}' found at ${CANDIDATE}/${CLI_CMD} but not in PATH"
      add_to_path "${CANDIDATE}"
    else
      die "'${CLI_CMD}' binary not found after installation. Check npm global bin: $(npm bin -g 2>/dev/null || echo 'unknown')"
    fi
  fi

  INSTALLED_VERSION=$("${CLI_CMD}" --version 2>/dev/null || echo "unknown")
  success "${CLI_CMD} ${INSTALLED_VERSION} is ready"
}

add_to_path() {
  local DIR="$1"
  warn "Adding ${DIR} to PATH"

  for RC in "${HOME}/.bashrc" "${HOME}/.zshrc" "${HOME}/.profile"; do
    if [ -f "${RC}" ] && ! grep -q "${DIR}" "${RC}"; then
      echo "" >> "${RC}"
      echo "# Added by NEXUS AI CLI installer" >> "${RC}"
      echo "export PATH=\"${DIR}:\$PATH\"" >> "${RC}"
    fi
  done

  export PATH="${DIR}:${PATH}"
  info "Run 'source ~/.bashrc' (or open a new terminal) to apply PATH changes."
}

# ── Configure API URL ─────────────────────────────────────────────────────────
configure() {
  step "Configuring CLI"

  mkdir -p "${CONFIG_DIR}"
  chmod 700 "${CONFIG_DIR}"

  if [[ "${API_URL}" != "${DEFAULT_API_URL}" ]]; then
    info "Setting API URL to ${API_URL}"
    local CONFIG_FILE="${CONFIG_DIR}/config.json"

    # Merge with existing config if present
    if [ -f "${CONFIG_FILE}" ]; then
      # Update apiUrl in existing config (portable sed)
      local TMP
      TMP=$(mktemp)
      python3 -c "
import json, sys
with open('${CONFIG_FILE}') as f:
    cfg = json.load(f)
cfg['apiUrl'] = '${API_URL}'
print(json.dumps(cfg, indent=2))
" > "${TMP}" 2>/dev/null && mv "${TMP}" "${CONFIG_FILE}" || {
        # Fallback without python3
        echo "{\"apiUrl\":\"${API_URL}\"}" > "${CONFIG_FILE}"
      }
    else
      echo "{\"apiUrl\":\"${API_URL}\"}" > "${CONFIG_FILE}"
    fi

    chmod 600 "${CONFIG_FILE}"
    success "API URL configured: ${API_URL}"
  else
    info "Using default API URL: ${DEFAULT_API_URL}"
  fi
}

# ── Uninstall ─────────────────────────────────────────────────────────────────
uninstall() {
  step "Uninstalling NEXUS AI CLI"

  if command -v "${CLI_CMD}" &>/dev/null; then
    if [ -w "$(npm config get prefix 2>/dev/null || echo '/usr/local')" ] || [[ $EUID -eq 0 ]]; then
      npm uninstall -g "${CLI_NAME}"
    else
      need_sudo npm uninstall -g "${CLI_NAME}"
    fi
    success "${CLI_CMD} binary removed"
  else
    warn "${CLI_CMD} not found in PATH — skipping binary removal"
  fi

  if [ -d "${CONFIG_DIR}" ]; then
    read -r -p "  Remove configuration at ${CONFIG_DIR}? [y/N] " CONFIRM
    if [[ "${CONFIRM}" =~ ^[Yy]$ ]]; then
      rm -rf "${CONFIG_DIR}"
      success "Configuration removed"
    else
      info "Configuration kept at ${CONFIG_DIR}"
    fi
  fi

  success "NEXUS AI CLI uninstalled"
  exit 0
}

# ── Post-install message ──────────────────────────────────────────────────────
print_success() {
  echo ""
  echo "────────────────────────────────────────────────────────────────"
  echo "${GREEN}${BOLD}  NEXUS AI CLI installed successfully!${RESET}"
  echo "────────────────────────────────────────────────────────────────"
  echo ""
  echo "  ${BOLD}Get started:${RESET}"
  echo ""
  echo "  ${CYAN}1. Log in to your account:${RESET}"
  echo "     ${BOLD}${CLI_CMD} auth login${RESET}"
  echo ""
  echo "  ${CYAN}2. List your deployments:${RESET}"
  echo "     ${BOLD}${CLI_CMD} deploy list${RESET}"
  echo ""
  echo "  ${CYAN}3. Create a new deployment:${RESET}"
  echo "     ${BOLD}${CLI_CMD} deploy create --name my-app --image my-org/my-app:latest${RESET}"
  echo ""
  echo "  ${CYAN}4. Stream live logs:${RESET}"
  echo "     ${BOLD}${CLI_CMD} deploy logs <deployment-id> --follow${RESET}"
  echo ""
  echo "  ${CYAN}5. View all commands:${RESET}"
  echo "     ${BOLD}${CLI_CMD} --help${RESET}"
  echo ""
  echo "  API endpoint: ${BLUE}${API_URL}${RESET}"
  echo "  Config dir:   ${CONFIG_DIR}"
  echo ""
  echo "  ${BOLD}Docs:${RESET}  ${BLUE}https://nexusai.run/docs${RESET}"
  echo "  ${BOLD}Issues:${RESET} ${BLUE}https://github.com/nexusrun/nexusai/issues${RESET}"
  echo ""
}

# ── Main ──────────────────────────────────────────────────────────────────────
main() {
  print_banner

  if [[ "${UNINSTALL}" == "true" ]]; then
    uninstall
  fi

  check_os
  check_node
  install_cli
  configure
  print_success
}

main "$@"
