#!/usr/bin/env bash

# Lockfiles that mean "a package manager the runner can actually install from".
PACKAGE_OWNER_JS_LOCKS="pnpm-lock.yaml package-lock.json bun.lock bun.lockb"
# composer.lock owns nothing the runner installs; it is listed here only so a
# PHP-only repository still resolves a workspace root instead of failing closed.
PACKAGE_OWNER_ANY_LOCKS="$PACKAGE_OWNER_JS_LOCKS composer.lock"

# Walk up from $2 to $mirror, returning the first directory that holds one of
# the lockfile names in $3.
package_owner_from_dir() {
  local mirror=$1 d=$2 locks=$3 lock
  while :; do
    for lock in $locks; do
      if [ -f "$d/$lock" ]; then
        printf '%s\n' "$d"
        return 0
      fi
    done
    [ "$d" = "$mirror" ] && return 1
    d=$(dirname "$d")
    case "$d/" in "$mirror/"*) ;; *) return 1 ;; esac
  done
}

# cwd walk first, then any existing path named by the command arguments.
package_owner_scan() {
  local mirror=$1 start=$2 locks=$3
  shift 3
  local owner candidate arg token

  if owner=$(package_owner_from_dir "$mirror" "$start" "$locks"); then
    printf '%s\n' "$owner"
    return 0
  fi

  # A compound argument (a `sh -c` script) names its paths as plain words, so
  # each whitespace token is a candidate too; a spaceless arg is its own token.
  for arg in "$@"; do
    for token in $arg; do
      case "$token" in
        /*) candidate=$token ;;
        *) candidate="$start/$token" ;;
      esac
      [ -e "$candidate" ] || continue
      [ -d "$candidate" ] || candidate=$(dirname "$candidate")
      if owner=$(package_owner_from_dir "$mirror" "$candidate" "$locks"); then
        printf '%s\n' "$owner"
        return 0
      fi
    done
  done

  return 1
}

find_package_owner() {
  local mirror=$1 rel=$2
  shift 2
  local start="$mirror${rel:+/$rel}" owner=""

  # Two passes, JS first. A PHP repository carrying composer.lock at its root
  # would otherwise claim ownership on the cwd walk and short-circuit the
  # argument scan that resolves a nested JS test package (e.g. `--dir tests/e2e`),
  # leaving a workspace root the runner never installs — and therefore no
  # node_modules/.bin for the client command to run.
  if owner=$(package_owner_scan "$mirror" "$start" "$PACKAGE_OWNER_JS_LOCKS" "$@"); then
    printf '%s\n' "$owner"
    return 0
  fi
  if owner=$(package_owner_scan "$mirror" "$start" "$PACKAGE_OWNER_ANY_LOCKS" "$@"); then
    printf '%s\n' "$owner"
    return 0
  fi

  return 1
}
