#!/usr/bin/env bash
set -euo pipefail
KIT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
CONFIG=${1:-"$KIT/config/deploy.env"}
[ "$(id -u)" = 0 ] || { echo '请由管理员执行，PM2仍使用APP_USER运行'; exit 1; }
set -a
source "$CONFIG"
set +a
bash "$KIT/scripts/check.sh" "$CONFIG"
NODE_DIR=$(dirname "$NODE_BIN")
APP_HOME=$(getent passwd "$APP_USER" | cut -d: -f6)
[ -n "$APP_HOME" ] && [ -d "$APP_HOME" ] || { echo "运行账号家目录不存在"; exit 1; }
# nginx -t只检查语法，不判断监听端口占用；首次启用前单独检查。
"$NODE_BIN" - "$SCHOOL_PORT" "$REGULATOR_PORT" "$SCREEN_PORT" "$MOBILE_PORT" "$GATEWAY_PORT" <<'JS'
const net=require('net');
(async()=>{for(const port of process.argv.slice(2)){await new Promise((resolve,reject)=>{const s=net.createServer();s.once('error',()=>reject(Error('端口已占用或不可监听: '+port)));s.listen(Number(port),'0.0.0.0',()=>s.close(resolve));});}})().catch(e=>{console.error(e.message);process.exitCode=1});
JS
(cd "$APP_ROOT" && runuser -u "$APP_USER" -- "$NODE_BIN" < "$KIT/scripts/dm-readonly-probe.cjs")
NAME="foodsafe-$INSTANCE"
TARGET="$NGINX_VHOST_DIR/foodsafe-release-$INSTANCE.conf"
[ -d "$NGINX_VHOST_DIR" ] || { echo 'Nginx include目录不存在'; exit 1; }
[ ! -e "$TARGET" ] && [ ! -L "$TARGET" ] || { echo '已有同名站点文件，先备份并审核'; exit 1; }
runpm2() { (cd "$APP_ROOT" && runuser -u "$APP_USER" -- env HOME="$APP_HOME" PM2_HOME="$APP_HOME/.pm2" PATH="$NODE_DIR:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" "$PM2_BIN" "$@"); }
runpm2 ping >/dev/null
runpm2 jlist | "$NODE_BIN" -e 'let s="";process.stdin.on("data",b=>s+=b);process.stdin.on("end",()=>{const rows=JSON.parse(s);if(rows.some(p=>p.name===process.argv[1])){console.error("已有同名PM2进程，停止以免覆盖");process.exit(1)}})' "$NAME"
install -m 644 "$APP_ROOT/deploy/nginx.conf" "$TARGET"
if ! "$NGINX_BIN" -t; then
  rm -- "$TARGET"
  echo '新站点语法或端口冲突检查失败，已撤销本次站点文件；原服务未重载'
  exit 1
fi
if ! runpm2 start "$APP_ROOT/deploy/ecosystem.config.cjs"; then
  runpm2 delete "$NAME" || true
  rm -- "$TARGET"
  echo '后端启动失败，请看本套日志；未重载Nginx'
  exit 1
fi
READY=0
for n in $(seq 1 30); do
  if curl --fail --silent --max-time 2 "http://127.0.0.1:$GATEWAY_PORT/health" >/dev/null; then READY=1; break; fi
  sleep 1
done
if [ "$READY" != 1 ]; then
  runpm2 delete "$NAME" || true
  rm -- "$TARGET"
  echo '后端健康失败，已停止本次新进程和站点配置；查看本套logs/error*.log'
  exit 1
fi
if ! "$NGINX_BIN" -s reload; then
  runpm2 delete "$NAME" || true
  rm -- "$TARGET"
  "$NGINX_BIN" -s reload || true
  echo 'Nginx重载失败，已撤销本次新增配置和后端；请检查Nginx服务及错误日志'
  exit 1
fi
if ! runpm2 save; then
  echo '本套服务已经运行，但PM2保存失败；请修复该用户PM2权限并重新save后再验收开机恢复'
  exit 1
fi
printf '启动完成：%s://%s:%s/\n' "$PUBLIC_SCHEME" "$PUBLIC_HOST" "$SCHOOL_PORT"
echo '还需按手册设置APP_USER的PM2开机恢复并做完整业务验收。'
