# activate-repo-node.sh — pin the target repo's declared Node for non-interactive spawns
#
# Sourced by orchestration scripts that run yarn/webpack in tmux, nohup, or other
# environments whose PATH may not match an interactive dev shell (.tool-versions and
# asdf shims are not applied automatically).
#
# On success sets:
#   REPO_NODE_VERSION — e.g. 24.13.0 (no leading v)
#   REPO_NODE_BIN     — absolute path to the node binary
#   REPO_NODE_BIN_DIR — dirname of REPO_NODE_BIN
#   REPO_NODE_PATH_PREFIX — "${REPO_NODE_BIN_DIR}:" when resolved, else empty
#
# Also prepends REPO_NODE_BIN_DIR to PATH in the current shell when resolved.
#
# Usage (after cd to target repo, or pass directory as $1):
#   . /path/to/activate-repo-node.sh
#   activate_repo_node [target-dir]
#
# Returns 0 when a declared version exists and a matching node binary was resolved;
# 1 when no version is declared; 2 when declared but no manager provided it.

_repo_node_matches_req() {
  local req="$1" actual="${2:-}"
  [ -n "$actual" ] || actual="$("$REPO_NODE_BIN" -v 2>/dev/null || true)"
  [ -n "$actual" ] || return 1
  actual="${actual#v}"
  [ "$actual" = "$req" ] && return 0
  case "$req" in
    *.*.*) return 1 ;;
    *.*) [[ "$actual" == "$req."* ]] ;;
    *) [[ "$actual" == "$req"* ]] ;;
  esac
}

_repo_node_set_from_bin() {
  local candidate="$1"
  [ -n "$candidate" ] && [ -x "$candidate" ] || return 1
  REPO_NODE_BIN="$candidate"
  REPO_NODE_BIN_DIR="$(cd "$(dirname "$REPO_NODE_BIN")" && pwd)"
  REPO_NODE_PATH_PREFIX="${REPO_NODE_BIN_DIR}:"
  export PATH="${REPO_NODE_BIN_DIR}:${PATH}"
  return 0
}

_repo_node_try_req() {
  local target="$1" req="$2" manager=""
  [ -n "$req" ] || return 1
  REPO_NODE_VERSION="$req"

  if command -v asdf >/dev/null 2>&1; then
    local asdf_root
    asdf_root="$(asdf where nodejs "$req" 2>/dev/null || true)"
    if [ -n "$asdf_root" ] && _repo_node_set_from_bin "$asdf_root/bin/node" && _repo_node_matches_req "$req"; then
      manager=asdf
      echo "[env] node $("$REPO_NODE_BIN" -v) from .tool-versions/.nvmrc via asdf ($req)" >&2
      return 0
    fi
  fi

  if command -v fnm >/dev/null 2>&1; then
    local fnm_bin
    fnm_bin="$(fnm exec --using "$req" -- which node 2>/dev/null || true)"
    if _repo_node_set_from_bin "$fnm_bin" && _repo_node_matches_req "$req"; then
      echo "[env] node $("$REPO_NODE_BIN" -v) from .tool-versions/.nvmrc via fnm ($req)" >&2
      return 0
    fi
  fi

  if command -v mise >/dev/null 2>&1; then
    local mise_bin
    mise_bin="$(mise x -C "$target" -- which node 2>/dev/null || true)"
    if _repo_node_set_from_bin "$mise_bin" && _repo_node_matches_req "$req"; then
      echo "[env] node $("$REPO_NODE_BIN" -v) from .tool-versions/.nvmrc via mise ($req)" >&2
      return 0
    fi
  fi
  return 1
}

activate_repo_node() {
  local target="${1:-.}"
  REPO_NODE_VERSION=""
  REPO_NODE_BIN=""
  REPO_NODE_BIN_DIR=""
  REPO_NODE_PATH_PREFIX=""

  local declared=false tool_ver="" nvmrc="" req="" nvm_dir path_node
  if [ -f "$target/.tool-versions" ]; then
    declared=true
    tool_ver="$(awk '/^nodejs / {print $2; exit}' "$target/.tool-versions")"
    _repo_node_try_req "$target" "$tool_ver" && return 0
  fi
  if [ -f "$target/.nvmrc" ]; then
    declared=true
    nvmrc="$(tr -d ' \t\r\nv' < "$target/.nvmrc")"
    _repo_node_try_req "$target" "$nvmrc" && return 0
    case "$nvmrc" in
      *.*.*) ;;
      *.*) _repo_node_try_req "$target" "${nvmrc}.0" && return 0 ;;
    esac
  fi

  if [ "$declared" != true ]; then
    echo "[env] no node version declared in .nvmrc or .tool-versions" >&2
    return 1
  fi

  req="${tool_ver:-$nvmrc}"
  if [ -z "$req" ]; then
    echo "[env] node version file present but no nodejs entry in .tool-versions / .nvmrc" >&2
    return 1
  fi
  REPO_NODE_VERSION="$req"
  nvm_dir="${NVM_DIR:-$HOME/.nvm}"
  if [ -s "$nvm_dir/nvm.sh" ]; then
    # shellcheck disable=SC1090,SC1091
    . "$nvm_dir/nvm.sh"
    nvm use "$req" >/dev/null 2>&1 || nvm install "$req" >/dev/null 2>&1 || true
  fi

  path_node="$(command -v node 2>/dev/null || true)"
  if _repo_node_set_from_bin "$path_node" && _repo_node_matches_req "$req"; then
    echo "[env] node $("$REPO_NODE_BIN" -v) already on PATH ($req)" >&2
    return 0
  fi

  REPO_NODE_BIN=""
  REPO_NODE_BIN_DIR=""
  REPO_NODE_PATH_PREFIX=""
  echo "[env] need node ${req} (from .nvmrc / .tool-versions) but no installed manager provided it" >&2
  return 2
}

require_repo_node() {
  local target="${1:-.}"
  if ! command -v activate_repo_node >/dev/null 2>&1; then
    echo "[env] activate-repo-node.sh is not sourced; reinstall the harness (mm-harness install)" >&2
    return 1
  fi
  activate_repo_node "$target" || {
    echo "[env] refusing to run yarn/webpack without a pinned Node for $target" >&2
    return 1
  }
}
