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

log() {
  printf "[lexis-install] %s\n" "$*"
}

fail() {
  printf "[lexis-install] error: %s\n" "$*" >&2
  exit 1
}

has_cmd() {
  command -v "$1" >/dev/null 2>&1
}

require_cmd() {
  if ! has_cmd "$1"; then
    fail "missing required command: $1"
  fi
}

run_with_optional_sudo() {
  if [ "$(id -u)" -eq 0 ]; then
    "$@"
    return $?
  fi

  if has_cmd sudo; then
    sudo "$@"
    return $?
  fi

  return 1
}

ensure_npm_installed() {
  if has_cmd npm; then
    return 0
  fi

  log "npm not found. Attempting to install Node.js + npm..."

  case "$(uname -s)" in
    Darwin)
      ensure_homebrew_available
      brew install node
      ;;
    Linux)
      if has_cmd apt-get; then
        run_with_optional_sudo apt-get update || fail "failed to run apt-get update"
        run_with_optional_sudo apt-get install -y nodejs npm || fail "failed to install nodejs/npm with apt-get"
      elif has_cmd dnf; then
        run_with_optional_sudo dnf install -y nodejs npm || fail "failed to install nodejs/npm with dnf"
      elif has_cmd yum; then
        run_with_optional_sudo yum install -y nodejs npm || fail "failed to install nodejs/npm with yum"
      elif has_cmd pacman; then
        run_with_optional_sudo pacman -Sy --noconfirm nodejs npm || fail "failed to install nodejs/npm with pacman"
      elif has_cmd zypper; then
        run_with_optional_sudo zypper --non-interactive install nodejs npm || fail "failed to install nodejs/npm with zypper"
      elif has_cmd apk; then
        run_with_optional_sudo apk add --no-cache nodejs npm || fail "failed to install nodejs/npm with apk"
      else
        install_node_with_nvm_fallback
      fi
      ;;
    *)
      fail "unsupported platform for auto-installing npm"
      ;;
  esac

  if ! has_cmd npm; then
    fail "npm is still unavailable after auto-install attempt"
  fi
}

install_node_with_nvm_fallback() {
  if ! has_cmd curl; then
    fail "npm is missing, no supported package manager found, and curl is unavailable for nvm fallback"
  fi

  log "No supported package manager found. Installing Node.js via nvm fallback..."

  export NVM_DIR="$HOME/.nvm"
  if [ ! -s "$NVM_DIR/nvm.sh" ]; then
    curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
  fi

  . "$NVM_DIR/nvm.sh"
  nvm install --lts
  nvm use --lts
}

ensure_homebrew_available() {
  if has_cmd brew; then
    return 0
  fi

  if ! has_cmd curl; then
    fail "Homebrew is required on macOS but curl is not installed"
  fi

  log "Homebrew not found. Installing Homebrew..."
  NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

  if [ -x "/opt/homebrew/bin/brew" ]; then
    export PATH="/opt/homebrew/bin:$PATH"
  elif [ -x "/usr/local/bin/brew" ]; then
    export PATH="/usr/local/bin:$PATH"
  fi

  if ! has_cmd brew; then
    fail "Homebrew installation completed but brew is unavailable. Open a new shell and rerun installer."
  fi
}

append_user_path_exports() {
  local line='export PATH="$HOME/.local/bin:$PATH"'
  local rc

  for rc in "$HOME/.profile" "$HOME/.bashrc" "$HOME/.zshrc"; do
    if [ ! -f "$rc" ]; then
      touch "$rc"
    fi

    if ! grep -Fq "$line" "$rc"; then
      printf "\n%s\n" "$line" >> "$rc"
    fi
  done
}

install_global_with_fallbacks() {
  local source="$1"

  if npm install -g "$source"; then
    return 0
  fi

  if [ "$(id -u)" -ne 0 ] && has_cmd sudo; then
    log "Global install needs elevated permissions. Retrying with sudo..."
    if sudo npm install -g "$source"; then
      return 0
    fi
  fi

  local user_prefix="$HOME/.local"
  log "Falling back to user-level npm prefix: $user_prefix"
  npm install -g --prefix "$user_prefix" "$source"
  export PATH="$user_prefix/bin:$PATH"
  append_user_path_exports
  return 0
}

ensure_npm_installed
require_cmd node
require_cmd npm

SOURCE="${LEXIS_INSTALL_SOURCE:-@hridyacodes/lexis}"
log "Installing Lexis from: $SOURCE"
install_global_with_fallbacks "$SOURCE"

if ! has_cmd lexis; then
  fail "'lexis' command not found after install"
fi

HOOK_MODE="${LEXIS_HOOK_MODE:-}"
PROFILE="${LEXIS_PROFILE:-}"

ARGS=(setup --enable-web-search --web-provider mcp)
if [ -n "$PROFILE" ]; then
  ARGS+=(--profile "$PROFILE")
fi
if [ -n "$HOOK_MODE" ]; then
  ARGS+=(--hook-mode "$HOOK_MODE")
fi

log "Running setup"
lexis "${ARGS[@]}"

log "Done. Open a new terminal and run: lx doctor"
