#!/bin/bash
# fleet-recover.sh — 恢复某台 fleet 机器的 Hermes dashboard（mac 版）
#
# 用法（在目标 mac 的 Terminal 里跑）：
#   bash <(curl -s https://<hub>/fleet-recover.sh) <label> <plist-abs-path>
# 或直接：
#   bash fleet-recover.sh com.hermes.serve /Users/mac/Library/LaunchAgents/com.hermes.serve.plist
#
# 做什么：
#   1. 用 `launchctl kickstart` 重启 dashboard 进程（不动 job 定义，不会自杀）
#   2. 如果 kickstart 失败（job 未加载），退回到 bootout+load，但把 load 放在
#      bootout 之前会失败，所以这里用 `launchctl enable` + `bootstrap`，
#      并且用 setsid 脱离当前进程组，避免 dashboard 退出时 SIGTERM 打断脚本。
#
# 重要：本脚本绝不能由 dashboard 自己的 cron job 执行（bootout 会杀掉自己）。

set -u

LABEL="${1:-}"
PLIST="${2:-}"

if [ -z "$LABEL" ] || [ -z "$PLIST" ]; then
  echo "用法: $0 <launchd-label> <plist-abs-path>"
  echo "例:   $0 com.hermes.serve /Users/mac/Library/LaunchAgents/com.hermes.serve.plist"
  exit 2
fi

uid="$(id -u)"
echo "== 目标: label=$LABEL plist=$PLIST"

if [ ! -f "$PLIST" ]; then
  echo "!! plist 不存在: $PLIST"
  exit 3
fi

# 1) 先试 kickstart：重启进程但保留 job 定义（最安全，不自杀）
echo "-- launchctl kickstart -k gui/$uid/$LABEL"
launchctl kickstart -k "gui/$uid/$LABEL" 2>&1 | head -3
sleep 4

if lsof -nP -iTCP:9119 -sTCP:LISTEN >/dev/null 2>&1; then
  echo "== OK: 9119 已监听 =="
  lsof -nP -iTCP:9119 -sTCP:LISTEN 2>/dev/null | head -3
  exit 0
fi

# 2) kickstart 失败 -> job 未加载。用 bootstrap 重新加载（比 load 新，且 cron
#    守护只封 submit|bootstrap，bootout/load/kickstart 允许；本脚本由用户在
#    终端手跑，不受 cron 守护限制）。
echo "-- 9119 未监听，改用 bootout + bootstrap"
launchctl bootout "gui/$uid/$LABEL" 2>&1 | head -3
sleep 2
launchctl bootstrap "gui/$uid" "$PLIST" 2>&1 | head -3
sleep 3

if lsof -nP -iTCP:9119 -sTCP:LISTEN >/dev/null 2>&1; then
  echo "== OK: 9119 已监听 =="
  lsof -nP -iTCP:9119 -sTCP:LISTEN 2>/dev/null | head -3
  exit 0
fi

# 3) 兜底：直接拉起一个 dashboard 进程（不依赖 launchd）
echo "-- 兜底：直接启动 dashboard 进程"
HERMES_BIN=""
for c in "$HOME/.hermes/hermes-agent/venv/bin/hermes" "$HOME/.hermes/hermes-agent/.hermes/bin/hermes" "$HOME/.hermes/bin/hermes"; do
  [ -x "$c" ] && HERMES_BIN="$c" && break
done
if [ -z "$HERMES_BIN" ]; then
  echo "!! 找不到 hermes 可执行文件"
  exit 4
fi
echo "   用 $HERMES_BIN"
setsid "$HERMES_BIN" dashboard --port 9119 --host 0.0.0.0 --no-open \
  > /tmp/hermes-dashboard-recover.log 2>&1 &
sleep 6
if lsof -nP -iTCP:9119 -sTCP:LISTEN >/dev/null 2>&1; then
  echo "== OK: 9119 已监听（直接启动）=="
  lsof -nP -iTCP:9119 -sTCP:LISTEN 2>/dev/null | head -3
  exit 0
fi

echo "!! 恢复失败，最后的日志："
tail -20 /tmp/hermes-dashboard-recover.log 2>/dev/null
exit 5
