#!/usr/bin/env bash
# reap-checkout-metros.sh — find/kill Metro (Expo) bundlers bound to a checkout.
# The harness starts Metro exactly one way: `yarn expo start`. Match ONLY that
# signature — matching bare "metro" also caught the `tail -F …/metro.log` viewer
# and other noise, producing false orphans.
#
#   reap_checkout_metros  <checkout-abs-path> [keep-pid]
#   detect_checkout_metros <checkout-abs-path> [live-port]
# reap kills every bundler for the checkout (stop wants a clean slate), sparing
# keep-pid. detect lists orphans for doctor and EXCLUDES the bundler serving
# live-port (the currently-running valid Metro is not a leak).

_checkout_metro_pids() {
  # pids of `expo start` bundlers whose argv references this checkout (boundary
  # anchored so /repos/mm-1 never matches /repos/mm-10).
  local repo="$1" pid args
  while IFS= read -r pid; do
    [ -n "$pid" ] || continue
    args="$(ps -o args= -p "$pid" 2>/dev/null || true)"
    case "$args" in *"$repo/"*|*"$repo "*) : ;; *) continue ;; esac
    case "$args" in *"expo start"*) printf '%s\n' "$pid" ;; esac
  done <<LIST
$(pgrep -f "expo start" 2>/dev/null)
LIST
}

reap_checkout_metros() {
  local repo="$1" keep="${2:-}" reaped="" pid
  [ -n "$repo" ] || return 0
  while IFS= read -r pid; do
    [ -n "$pid" ] || continue
    [ "$pid" = "$keep" ] && continue
    kill "$pid" 2>/dev/null && reaped="$reaped $pid"
  done <<LIST
$(_checkout_metro_pids "$repo")
LIST
  if [ -n "$reaped" ]; then
    printf 'Reaped leaked Metro bundler(s) for this checkout:%s\n' "$reaped" >&2
  fi
  return 0
}

reap_checkout_metros_on_port() {
  local repo="$1" port="$2" reaped="" pid args
  [ -n "$repo" ] && [ -n "$port" ] || return 0
  while IFS= read -r pid; do
    [ -n "$pid" ] || continue
    args="$(ps -o args= -p "$pid" 2>/dev/null || true)"
    case " $args " in *" --port $port "*|*" --port=$port "*) ;; *) continue ;; esac
    kill "$pid" 2>/dev/null && reaped="$reaped $pid"
  done <<LIST
$(_checkout_metro_pids "$repo")
LIST
  if [ -n "$reaped" ]; then
    printf 'Reaped leaked Metro bundler(s) for checkout port %s:%s\n' "$port" "$reaped" >&2
  fi
  return 0
}

detect_checkout_metros() {
  local repo="$1" live_port="${2:-}" pid args
  [ -n "$repo" ] || return 0
  while IFS= read -r pid; do
    [ -n "$pid" ] || continue
    # A bundler serving the currently-managed port is the LIVE valid Metro, not
    # an orphan — exclude it so doctor never flags the running server.
    if [ -n "$live_port" ]; then
      args="$(ps -o args= -p "$pid" 2>/dev/null || true)"
      case "$args" in *"--port $live_port"*|*"--port=$live_port"*) continue ;; esac
    fi
    printf '%s\n' "$pid"
  done <<LIST
$(_checkout_metro_pids "$repo")
LIST
}
