#!/usr/bin/env bash
# 代码/镜像更新（服务器上不改库）— 任一步失败立即中断
# 用法：
#   1) 本机 DataGrip 已执行 deploy/datagrip-manual-migrate-20260716.sql
#   2) 服务器：bash deploy/update-code-only-bt-host-mysql.sh
#
# 特点：串行 build；跳过 migrate/seed；失败 fail-fast，不继续后续步骤

set -euo pipefail

ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
COMPOSE_FILE="${ROOT_DIR}/deploy/docker-compose.bt-host-mysql.yml"
ENV_FILE="${ROOT_DIR}/.env"

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

log() { echo -e "${GREEN}[update-code]${NC} $*"; }
warn() { echo -e "${YELLOW}[update-code]${NC} $*"; }
err() { echo -e "${RED}[update-code]${NC} $*" >&2; }

CURRENT_STEP="init"
on_err() {
  local code=$?
  err "失败中断：步骤「${CURRENT_STEP}」退出码=${code}"
  err "已停止继续执行（不会启动半成品镜像）。请根据上方日志修复后重跑本脚本。"
  err "若容器已 stop：修复后重新执行本脚本即可恢复。"
  exit "$code"
}
trap on_err ERR

require_file() {
  local path="$1"
  if [[ ! -f "$path" ]]; then
    err "缺少文件: $path"
    exit 1
  fi
}

require_env_key() {
  local key="$1"
  if ! grep -qE "^[[:space:]]*${key}=" "$ENV_FILE"; then
    err ".env 缺少 ${key}（新功能不会生效）"
    exit 1
  fi
}

run_step() {
  local name="$1"
  shift
  CURRENT_STEP="$name"
  log "→ ${name}"
  "$@"
  log "✓ ${name} 完成"
}

# ---------- 前置校验（失败立即退出）----------
CURRENT_STEP="preflight"
log "前置校验..."

if [[ ! -f "$ENV_FILE" ]]; then
  err "缺少 .env，禁止继续（避免误用模板覆盖生产配置）"
  exit 1
fi

if [[ ! -f "$COMPOSE_FILE" ]]; then
  err "缺少 compose 文件: $COMPOSE_FILE"
  exit 1
fi

if ! command -v docker >/dev/null 2>&1; then
  err "未安装 docker"
  exit 1
fi

if ! docker compose version >/dev/null 2>&1; then
  err "需要 Docker Compose V2"
  exit 1
fi

require_file "${ROOT_DIR}/app/api/flock/quotes/route.ts"
require_file "${ROOT_DIR}/workers/rpa/flock-freight.ts"
require_file "${ROOT_DIR}/workers/rpa/mothership-logged-in-quote.ts"
require_file "${ROOT_DIR}/Dockerfile"
require_file "${ROOT_DIR}/Dockerfile.worker"
require_file "${ROOT_DIR}/package.json"
require_file "${ROOT_DIR}/package-lock.json"

require_env_key "FLOCK_RPA_ENABLED"
require_env_key "NEXT_PUBLIC_FLOCK_POLL_TIMEOUT_MS"
require_env_key "DATABASE_URL"
require_env_key "JWT_SECRET"

if grep -qE "^[[:space:]]*RPA_BROWSER_CHANNEL=chrome" "$ENV_FILE"; then
  err ".env 存在 RPA_BROWSER_CHANNEL=chrome（Docker 内会启动失败），请删除该行后重跑"
  exit 1
fi

# 可用内存过低时警告（不强制中断，避免误杀）
if command -v free >/dev/null 2>&1; then
  avail_kb="$(free -k | awk '/^Mem:/{print $7}')"
  if [[ -n "${avail_kb:-}" && "$avail_kb" -lt 400000 ]]; then
    warn "可用内存偏低（约 $((avail_kb / 1024))MB），构建可能 OOM；建议先 stop 其他重负载或加 Swap"
  fi
fi

log "前置校验通过"

cd "$ROOT_DIR"
compose=(docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE")

export DOCKER_BUILDKIT=1
export BUILDKIT_MAX_PARALLELISM=1

# ---------- 串行更新（任一步失败由 trap 中断）----------
run_step "停止 next-app/rpa-worker/scheduler" \
  "${compose[@]}" stop next-app rpa-worker scheduler

run_step "构建 next-app" \
  "${compose[@]}" build next-app

run_step "构建 rpa-worker" \
  "${compose[@]}" build rpa-worker

run_step "构建 scheduler" \
  "${compose[@]}" build scheduler

run_step "启动全部服务" \
  "${compose[@]}" up -d

CURRENT_STEP="校验容器状态"
log "→ 校验容器状态"
"${compose[@]}" ps
# 关键服务必须处于 running
for svc in next-app rpa-worker scheduler redis; do
  state="$("${compose[@]}" ps --status running --services 2>/dev/null | grep -x "$svc" || true)"
  if [[ -z "$state" ]]; then
    err "服务未处于 running: ${svc}"
    err "查看日志: ${compose[*]} logs --tail 80 ${svc}"
    exit 1
  fi
  log "✓ ${svc} running"
done

CURRENT_STEP="done"
trap - ERR

warn "库结构须已在 DataGrip 用 SQL 改完（本脚本不碰库）"
warn "以后不要再跑 install-bt-host-mysql.sh（会自动 migrate）"
warn "建议清报价缓存："
echo "  ${compose[*]} exec redis redis-cli FLUSHDB"

log "完成（代码-only 更新，全程失败即中断）"
