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

repo_path_input="${1:-$PWD}"
shift || true

command_to_run=()
if [ "${1:-}" = "--" ]; then
  shift
  command_to_run=("$@")
fi

if [ ! -d "$repo_path_input" ]; then
  echo "Runtime check failed: repo path does not exist: $repo_path_input" >&2
  exit 2
fi

repo_path="$(cd "$repo_path_input" && pwd)"
cd "$repo_path"

package_json_path="$repo_path/package.json"
nvmrc_path="$repo_path/.nvmrc"

current_node=""
current_npm=""
expected_node_from_nvmrc=""
engine_node=""
engine_npm=""
expected_node=""
expected_npm=""
mismatch=0
auto_switch_attempted=0
auto_switch_succeeded=0

normalize_exact_version() {
  local value="$1"
  value="${value#v}"
  if [[ "$value" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
    echo "$value"
    return 0
  fi
  return 1
}

load_nvm() {
  if command -v nvm >/dev/null 2>&1; then
    return 0
  fi

  export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
  if [ -s "$NVM_DIR/nvm.sh" ]; then
    # shellcheck source=/dev/null
    . "$NVM_DIR/nvm.sh"
  fi

  if command -v nvm >/dev/null 2>&1; then
    return 0
  fi

  if [ -s "/opt/homebrew/opt/nvm/nvm.sh" ]; then
    # shellcheck source=/dev/null
    . "/opt/homebrew/opt/nvm/nvm.sh"
  fi

  command -v nvm >/dev/null 2>&1
}

refresh_current_versions() {
  if command -v node >/dev/null 2>&1; then
    current_node="$(node -v | sed 's/^v//')"
  else
    current_node=""
  fi

  if command -v npm >/dev/null 2>&1; then
    current_npm="$(npm -v)"
  else
    current_npm=""
  fi
}

collect_expected_versions() {
  expected_node_from_nvmrc=""
  if [ -f "$nvmrc_path" ]; then
    expected_node_from_nvmrc="$(tr -d '[:space:]' < "$nvmrc_path" | sed 's/^v//')"
  fi

  engine_node=""
  engine_npm=""
  if [ -f "$package_json_path" ] && command -v node >/dev/null 2>&1; then
    engine_node="$(node -e 'const fs=require("fs");const pkg=JSON.parse(fs.readFileSync(process.argv[1],"utf8"));process.stdout.write((pkg.engines&&pkg.engines.node)||"");' "$package_json_path")"
    engine_npm="$(node -e 'const fs=require("fs");const pkg=JSON.parse(fs.readFileSync(process.argv[1],"utf8"));process.stdout.write((pkg.engines&&pkg.engines.npm)||"");' "$package_json_path")"
  fi

  expected_node=""
  expected_npm=""
  if [ -n "$expected_node_from_nvmrc" ]; then
    expected_node="$expected_node_from_nvmrc"
  fi
  if [ -z "$expected_node" ] && normalize_exact_version "$engine_node" >/dev/null 2>&1; then
    expected_node="$(normalize_exact_version "$engine_node")"
  fi
  if normalize_exact_version "$engine_npm" >/dev/null 2>&1; then
    expected_npm="$(normalize_exact_version "$engine_npm")"
  fi
}

compute_mismatch() {
  mismatch=0
  if [ -n "$expected_node" ] && [ "$current_node" != "$expected_node" ]; then
    mismatch=1
  fi
  if [ -n "$expected_npm" ] && [ "$current_npm" != "$expected_npm" ]; then
    mismatch=1
  fi
}

attempt_auto_switch() {
  local switch_target="$1"
  auto_switch_attempted=1

  if ! load_nvm; then
    return 1
  fi

  if [ -n "$switch_target" ]; then
    if nvm use "$switch_target" >/dev/null 2>&1; then
      auto_switch_succeeded=1
      return 0
    fi
  fi

  if nvm use >/dev/null 2>&1; then
    auto_switch_succeeded=1
    return 0
  fi

  return 1
}

refresh_current_versions
collect_expected_versions
compute_mismatch

if [ "$mismatch" -eq 1 ]; then
  switch_target="${expected_node_from_nvmrc:-$expected_node}"
  attempt_auto_switch "$switch_target" || true
  refresh_current_versions
  collect_expected_versions
  compute_mismatch
fi

if [ "$mismatch" -eq 1 ]; then
  echo "Runtime check failed for: $repo_path" >&2
  echo "Current: node=${current_node:-missing} npm=${current_npm:-missing}" >&2
  if [ -n "$expected_node" ]; then
    echo "Expected node: $expected_node" >&2
  fi
  if [ -n "$expected_npm" ]; then
    echo "Expected npm:  $expected_npm" >&2
  fi
  if [ "$auto_switch_attempted" -eq 1 ] && [ "$auto_switch_succeeded" -eq 0 ]; then
    echo "Auto-fix attempt: tried 'nvm use' and it did not resolve the mismatch." >&2
  fi
  echo "Fix: run 'nvm use' in the target repo and retry." >&2
  exit 1
fi

if [ -n "$engine_node" ] && [ -z "$expected_node" ]; then
  echo "Runtime check note: engines.node is not exact ('$engine_node'); strict check skipped."
fi

if [ -n "$engine_npm" ] && [ -z "$expected_npm" ]; then
  echo "Runtime check note: engines.npm is not exact ('$engine_npm'); strict check skipped."
fi

if [ "$auto_switch_succeeded" -eq 1 ]; then
  echo "Runtime check passed for: $repo_path after automatic nvm switch (node=$current_node npm=$current_npm)"
else
  echo "Runtime check passed for: $repo_path (node=$current_node npm=$current_npm)"
fi

if [ "${#command_to_run[@]}" -gt 0 ]; then
  "${command_to_run[@]}"
fi
