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

# This script wraps npm so to run `mise reshim` after global installs and uninstalls
# Any other cases are passed-through to npm

this_dir=$(dirname "${BASH_SOURCE[0]}")
plugin_name=$(basename "$(dirname "$this_dir")")

this_dir=$(cd "$this_dir" && pwd -P) # Normalizes the directory

plugin_dir="${this_dir}/.."

should_reshim() {
  if [ "${MISE_SKIP_RESHIM:-}" ]; then
    return 1
  fi

  local is_global='' cmd='' cmd_needs_reshim=''
  local additional_bare_cmds=()
  local has_workspace_flag=false
  local has_package_operand=false

  for arg; do
    case "$arg" in
    -g | --global)
      is_global=true
      ;;

    --workspace=*)
      has_workspace_flag=true
      ;;

    --workspace | -w)
      # Next arg is workspace name - will be caught in next iteration
      has_workspace_flag=true
      ;;

    -*) ;; # Skip other options

    *)
      if ! [ "$cmd" ]; then
        cmd="$arg"
      else
        additional_bare_cmds+=("$arg")
        # First bare arg after cmd is the package operand
        if [ "${#additional_bare_cmds[@]}" -eq 1 ]; then
          has_package_operand=true
        fi
      fi
      ;;
    esac
  done

  case "$cmd" in
  # npm install aliases
  install | i | in | ins | inst | insta | instal | isnt | isnta | isntal | add)
    cmd_needs_reshim=true
    ;;

  # npm uninstall aliases
  uninstall | un | unlink | remove | rm | r)
    cmd_needs_reshim=true
    ;;

  link | ln)
    # Workspace-local link: npm link <pkg> --workspace <name> (or -w)
    # Global workspace link: npm link --workspace <name> (no package operand)
    if [ "$has_workspace_flag" = true ] && [ "$has_package_operand" = true ]; then
      is_global=''
      cmd_needs_reshim=''
    # Bare link installs a global package
    elif ! [ "${additional_bare_cmds[0]-}" ]; then
      is_global=1
      cmd_needs_reshim=true
    # Links to directories also install a global package
    elif [[ "${additional_bare_cmds[0]-}" =~ ^[./].* && -d "${additional_bare_cmds[0]-}" ]]; then
      is_global=1
      cmd_needs_reshim=true
    # npm link <package-name> also installs globally (creates symlink in global node_modules)
    elif [ "${additional_bare_cmds[0]-}" ]; then
      is_global=1
      cmd_needs_reshim=true
    fi
    ;;
  esac

  # Implicit return
  [ "$is_global" ] && [ "$cmd_needs_reshim" ]
}

wrap_npm_if_reshim_is_needed() {
  local npm_cli="$plugin_dir/lib/node_modules/npm/bin/npm-cli.js"
  local node_bin="$plugin_dir/bin/node"
  if should_reshim "$@"; then
    # Run npm and capture exit code without exiting on failure (set -e)
    "$node_bin" "$npm_cli" "$@"
    local npm_exit=$?
    printf "Reshimming mise %s...\n" "$plugin_name" >&2
    # Run mise reshim, ignore its exit code
    mise reshim || true
    # Return npm's exit code
    return $npm_exit
  else
    exec "$node_bin" "$npm_cli" "$@"
  fi
}

wrap_npm_if_reshim_is_needed "$@"