#!/usr/bin/env bash
# 拉取代码并重启：缺什么自动安装（curl、Git、Docker、Docker Compose），再 git 拉取 + docker compose 构建启动
# 用法：cd 项目根 && ./pull-and-restart.sh（仓库中已记录可执行权限，拉取后可直接执行）
# 行尾：LF
set -e
ROOT="${PROJECT_ROOT:-$(cd "$(dirname "$0")" && pwd)}"
cd "$ROOT"

run_sudo() { sudo "$@"; }

# ---------- 检测并安装 curl（下载 Docker Compose 等需要）----------
ensure_curl() {
  if command -v curl >/dev/null 2>&1; then
    return 0
  fi
  echo "未检测到 curl，正在安装..."
  if command -v apt-get >/dev/null 2>&1; then
    run_sudo apt-get update -qq
    run_sudo apt-get install -y curl
  elif command -v dnf >/dev/null 2>&1; then
    run_sudo dnf install -y curl
  elif command -v yum >/dev/null 2>&1; then
    run_sudo yum install -y curl
  else
    echo "无法自动安装 curl，请先安装 curl 后重试."
    exit 1
  fi
  echo "curl 已安装."
}

# ---------- 检测并安装 Git（国内服务器用系统源）----------
ensure_git() {
  if command -v git >/dev/null 2>&1; then
    return 0
  fi
  echo "未检测到 Git，正在安装..."
  if command -v apt-get >/dev/null 2>&1; then
    run_sudo apt-get update -qq
    run_sudo apt-get install -y git
  elif command -v dnf >/dev/null 2>&1; then
    run_sudo dnf install -y git
  elif command -v yum >/dev/null 2>&1; then
    run_sudo yum install -y git
  else
    echo "无法自动安装 Git，请先安装 Git 后重试."
    exit 1
  fi
  echo "Git 已安装."
}

# ---------- 检测并安装 Docker（用 run_sudo 检测，与后续 compose 一致；支持 Podman 兼容层）----------
ensure_docker() {
  if command -v docker >/dev/null 2>&1 && run_sudo docker info >/dev/null 2>&1; then
    echo "Docker 已就绪."
    return 0
  fi
  if command -v docker >/dev/null 2>&1; then
    echo "Docker/Podman 守护进程未连接，尝试启动..."
    run_sudo systemctl start podman 2>/dev/null || true
    run_sudo systemctl start docker 2>/dev/null || true
    if run_sudo docker info >/dev/null 2>&1; then
      echo "Docker 已就绪."
      return 0
    fi
    echo "错误：无法连接 Docker/Podman 守护进程，请执行: sudo systemctl start podman 或 sudo systemctl start docker" >&2
    exit 1
  fi
  echo "未检测到 Docker 或未启动，正在安装..."
  if command -v apt-get >/dev/null 2>&1; then
    run_sudo apt-get update -qq
    run_sudo apt-get install -y docker.io docker-compose-plugin 2>/dev/null || run_sudo apt-get install -y docker.io docker-compose
    run_sudo systemctl start docker
    run_sudo systemctl enable docker
  elif command -v dnf >/dev/null 2>&1 || command -v yum >/dev/null 2>&1; then
    if command -v dnf >/dev/null 2>&1; then
      run_sudo dnf install -y docker
    else
      run_sudo yum install -y docker
    fi
    run_sudo systemctl start docker
    run_sudo systemctl enable docker
  else
    echo "无法自动安装 Docker，请先安装 Docker 与 Docker Compose 后重试."
    exit 1
  fi
  echo "Docker 安装完成."
}

# ---------- 配置 Docker Hub 镜像加速（国内拉取超时时使用 Podman 镜像）----------
ensure_registry_mirror() {
  REG_CONF_D="/etc/containers/registries.conf.d"
  REG_MIRROR_CONF="$REG_CONF_D/99-docker-mirror.conf"
  echo "配置 Docker Hub 镜像加速（Podman）..."
  run_sudo mkdir -p "$REG_CONF_D"
  run_sudo tee "$REG_MIRROR_CONF" >/dev/null <<'REGEOF'
# 国内 Docker Hub 拉取加速，由 pull-and-restart.sh 生成（多镜像备用）
unqualified-search-registries = ["docker.io"]
[[registry]]
location = "docker.io"
[[registry.mirror]]
location = "docker.m.daocloud.io"
[[registry.mirror]]
location = "docker.1ms.run"
[[registry.mirror]]
location = "docker.xuanyuan.me"
REGEOF
  echo "已写入 $REG_MIRROR_CONF（docker.io 镜像: daocloud / 1ms / xuanyuan）."
}

# ---------- 检测并安装 Docker Compose（优先插件 docker compose，否则独立二进制）----------
ensure_docker_compose() {
  run_sudo docker compose version >/dev/null 2>&1 && return 0
  command -v docker-compose >/dev/null 2>&1 && return 0
  [ -x /usr/local/bin/docker-compose ] && return 0
  # 优先尝试用包管理器安装插件，避免独立二进制架构不符导致 Bus error
  echo "未检测到 Docker Compose，正在尝试安装（优先插件）..."
  if command -v dnf >/dev/null 2>&1; then
    run_sudo dnf install -y docker-compose-plugin 2>/dev/null || true
    if ! run_sudo docker compose version >/dev/null 2>&1; then
      echo "系统源无插件，尝试添加 Docker CE 源（阿里云镜像）..."
      run_sudo dnf install -y dnf-plugins-core 2>/dev/null || true
      run_sudo dnf config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 2>/dev/null || \
      run_sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 2>/dev/null || true
      run_sudo dnf install -y docker-compose-plugin 2>/dev/null || true
    fi
  elif command -v yum >/dev/null 2>&1; then
    run_sudo yum install -y docker-compose-plugin 2>/dev/null || true
    if ! run_sudo docker compose version >/dev/null 2>&1; then
      echo "系统源无插件，尝试添加 Docker CE 源（阿里云镜像）..."
      run_sudo yum install -y yum-utils 2>/dev/null || true
      run_sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 2>/dev/null || \
      run_sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 2>/dev/null || true
      run_sudo yum install -y docker-compose-plugin 2>/dev/null || true
    fi
  elif command -v apt-get >/dev/null 2>&1; then
    run_sudo apt-get update -qq 2>/dev/null; run_sudo apt-get install -y docker-compose-plugin 2>/dev/null || true
  fi
  run_sudo docker compose version >/dev/null 2>&1 && echo "Docker Compose 插件已就绪." && return 0
  # 回退：下载独立版（国内 DaoCloud 镜像）
  echo "正在安装独立版 Docker Compose（国内 DaoCloud 镜像）..."
  COMPOSE_ARCH="$(uname -m)"
  case "$COMPOSE_ARCH" in
    x86_64) COMPOSE_ARCH=x86_64 ;;
    aarch64|arm64) COMPOSE_ARCH=aarch64 ;;
    *) COMPOSE_ARCH=x86_64 ;;
  esac
  COMPOSE_VER="v2.24.0"
  COMPOSE_URL_CN="https://get.daocloud.io/docker/compose/releases/download/${COMPOSE_VER}/docker-compose-linux-${COMPOSE_ARCH}"
  if ! run_sudo curl -sfL --connect-timeout 20 --max-time 90 "$COMPOSE_URL_CN" -o /usr/local/bin/docker-compose; then
    COMPOSE_URL="https://github.com/docker/compose/releases/download/${COMPOSE_VER}/docker-compose-linux-${COMPOSE_ARCH}"
    run_sudo curl -sfL --max-time 90 "$COMPOSE_URL" -o /usr/local/bin/docker-compose
  fi
  run_sudo chmod +x /usr/local/bin/docker-compose
  # 若运行即崩溃（如 Bus error），删除以免后续误用
  run_sudo /usr/local/bin/docker-compose version >/dev/null 2>&1 || { run_sudo rm -f /usr/local/bin/docker-compose; echo "独立版运行失败（可能架构不符），请尝试: dnf install -y docker-compose-plugin 或 yum install -y docker-compose-plugin" >&2; return 0; }
  echo "Docker Compose 已安装."
}

# ---------- 检测并安装 Nginx（反代 + 强制 HTTPS，证书按域名存 /etc/ssl/yh_web/<域名>/）----------
ensure_nginx() {
  if command -v nginx >/dev/null 2>&1; then
    return 0
  fi
  echo "未检测到 Nginx，正在安装..."
  if command -v apt-get >/dev/null 2>&1; then
    run_sudo apt-get update -qq
    run_sudo apt-get install -y nginx
  elif command -v dnf >/dev/null 2>&1; then
    run_sudo dnf install -y nginx
  elif command -v yum >/dev/null 2>&1; then
    run_sudo yum install -y nginx
  else
    echo "无法自动安装 Nginx，请手动安装后重试."
    exit 1
  fi
  run_sudo systemctl enable nginx 2>/dev/null || true
  run_sudo systemctl start nginx 2>/dev/null || true
  echo "Nginx 已安装."
}

ensure_curl
ensure_git
ensure_docker
ensure_docker_compose
ensure_registry_mirror
ensure_nginx

# 确定要用的 compose 命令；测试独立二进制时用 || true 避免 Bus error 导致脚本退出
resolve_compose_cmd() {
  run_sudo docker compose version >/dev/null 2>&1 && echo "docker compose" && return
  if [ -x /usr/local/bin/docker-compose ]; then
    r=0; run_sudo /usr/local/bin/docker-compose version >/dev/null 2>&1 || r=1
    if [ "$r" -eq 0 ]; then echo "/usr/local/bin/docker-compose"; return; fi
    echo "检测到 /usr/local/bin/docker-compose 无法运行（可能架构不符），正在重装..." >&2
    run_sudo rm -f /usr/local/bin/docker-compose
    ensure_docker_compose || true
  fi
  run_sudo docker compose version >/dev/null 2>&1 && echo "docker compose" && return
  run_sudo docker-compose version >/dev/null 2>&1 && echo "docker-compose" && return
  ensure_docker_compose || true
  run_sudo docker compose version >/dev/null 2>&1 && echo "docker compose" && return
  if [ -x /usr/local/bin/docker-compose ]; then
    r=0; run_sudo /usr/local/bin/docker-compose version >/dev/null 2>&1 || r=1
    [ "$r" -eq 0 ] && echo "/usr/local/bin/docker-compose" || echo ""
  else
    echo ""
  fi
}
COMPOSE_CMD=""
compose_cmd() {
  if [ -z "$COMPOSE_CMD" ]; then
    COMPOSE_CMD="$(resolve_compose_cmd)"
  fi
  if [ -z "$COMPOSE_CMD" ]; then
    echo "错误：无法找到 docker compose 或 docker-compose，请手动安装到 /usr/local/bin/docker-compose"
    exit 1
  fi
  # sudo 默认不传环境变量，显式传入以便 compose 使用 REGISTRY_MIRROR / GOPROXY
  run_sudo env REGISTRY_MIRROR="${REGISTRY_MIRROR}" GOPROXY="${GOPROXY}" $COMPOSE_CMD "$@"
}

echo "=========================================="
echo "  yh_web 拉取并重启"
echo "  路径: $ROOT"
echo "=========================================="

# 环境配置：缺失时从 server/.env.example 复制（Docker 部署用 mongo:27017）
if [ ! -f server/.env ]; then
  if [ -f server/.env.example ]; then
    cp server/.env.example server/.env
    echo "已从 server/.env.example 创建 server/.env（可按需修改）."
  else
    mkdir -p server
    NGINX_DEFAULT_DOMAIN="${NGINX_DOMAIN:-yuheng.yuxindazhineng.com}"
    cat > server/.env <<ENVEOF
MONGODB_URI=mongodb://mongo:27017
MONGODB_DB=yxd-agent-testing
PORT=9527
GIN_MODE=release
ALLOWED_ORIGINS=https://${NGINX_DEFAULT_DOMAIN}
ENVEOF
    echo "已创建默认 server/.env（ALLOWED_ORIGINS=https://${NGINX_DEFAULT_DOMAIN}），可按需修改."
  fi
fi
[ -f server/.env ] && sed -i 's/\r$//' server/.env
[ -f server/.env ] && set -a && source server/.env && set +a

BRANCH="${GIT_BRANCH:-master}"
echo "[1/3] 拉取代码（以 Gitea 远程为准，本地修改会被覆盖）..."
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
  git fetch origin --progress
  git reset --hard "origin/$BRANCH"
else
  echo "未检测到 Git 仓库，正在克隆..."
  export GIT_TERMINAL_PROMPT=0
  # 默认仓库地址（仅本地/服务器使用，不提交到仓库；可覆盖：export GIT_REPO_URL=...）
  REPO_URL="${GIT_REPO_URL:-https://whm:02f8ceeee5f1aeb197ff400e4d97abbcf5550015@gitea.yuxindazhineng.com/whm/web.git}"
  SELF="$(basename "$0")"
  tmp_backup="/tmp/yh_web_deploy_$$"
  mkdir -p "$tmp_backup"
  [ -f "$SELF" ] && cp -a "$SELF" "$tmp_backup/"
  [ -f server/.env ] && cp -a server/.env "$tmp_backup/" 2>/dev/null || true
  git init -b "$BRANCH"
  git remote add origin "$REPO_URL"
  git fetch origin --progress
  git reset --hard "origin/$BRANCH"
  [ -f "$tmp_backup/$SELF" ] && cp -a "$tmp_backup/$SELF" "$SELF" && chmod +x "$SELF"
  [ -f "$tmp_backup/.env" ] && mkdir -p server && cp -a "$tmp_backup/.env" server/.env
  rm -rf "$tmp_backup"
fi

echo ""
echo "[2/3] 重新构建并启动..."
# 宿主机 9527 常被 sshd 占用，compose 必须使用 8088 且 api 不映射宿主机端口
if grep -q '9527' "$ROOT/docker-compose.yml" 2>/dev/null; then
  echo "错误: 当前 docker-compose.yml 仍含 9527，会与 sshd 冲突导致启动失败。请以 Gitea 为准拉取最新代码后再执行本脚本：" >&2
  echo "  git fetch origin && git reset --hard origin/master" >&2
  echo "若 Gitea 上已为 8088 仍报错，请本地提交并 push 后再在服务器执行上述命令。" >&2
  exit 1
fi
export GOPROXY="${GOPROXY:-https://goproxy.cn,direct}"
export REGISTRY_MIRROR="${REGISTRY_MIRROR:-docker.m.daocloud.io/library/}"

# 挂目录方案：构建产物到 deploy/，容器挂载这些目录，无需重建 web/admin 镜像
mkdir -p "$ROOT/deploy/web/dist" "$ROOT/deploy/admin/dist" "$ROOT/deploy/api"

echo "构建 web 前端 -> deploy/web/dist ..."
run_sudo docker run --rm -v "$ROOT/web:/app" -v "$ROOT/deploy/web/dist:/out" -w /app \
  "${REGISTRY_MIRROR}node:20-alpine" sh -c "rm -rf /out/* 2>/dev/null; (npm ci --legacy-peer-deps 2>/dev/null || npm install --legacy-peer-deps) && npm run build && cp -r dist/. /out/"

echo "构建 admin 前端 -> deploy/admin/dist ..."
run_sudo docker run --rm -v "$ROOT/admin:/app" -v "$ROOT/deploy/admin/dist:/out" -w /app \
  "${REGISTRY_MIRROR}node:20-alpine" sh -c "rm -rf /out/* 2>/dev/null; (npm ci --legacy-peer-deps 2>/dev/null || npm install --legacy-peer-deps) && npm run build && cp -r dist/. /out/"

echo "构建 api 二进制 -> deploy/api/server ..."
run_sudo docker run --rm -v "$ROOT/server:/src" -v "$ROOT/deploy/api:/out" -w /src -e GOPROXY="${GOPROXY}" \
  "${REGISTRY_MIRROR}golang:1.21-alpine" sh -c "go build -mod=vendor -o /out/server ."

# 确保容器内 nginx 可读（拉取后直接执行时权限一致）
run_sudo chmod -R a+rX "$ROOT/deploy/web/dist" "$ROOT/deploy/admin/dist" 2>/dev/null || true
if [ ! -f "$ROOT/deploy/web/dist/index.html" ] || [ ! -f "$ROOT/deploy/admin/dist/index.html" ]; then
  echo "错误: 构建产物不完整（缺少 index.html）。若仅做了 git pull 未执行本脚本，请完整执行: ./pull-and-restart.sh" >&2
  exit 1
fi

# 仅构建 api 运行时镜像（轻量，无业务代码）；web/admin 使用官方 nginx 镜像无需构建
compose_cmd build api

# 仅当本地没有 mongo:7 时才从镜像站拉取，避免每次重复下载约 250MB
MONGO_IMAGE="${REGISTRY_MIRROR}mongo:7"
if ! run_sudo docker image inspect "$MONGO_IMAGE" >/dev/null 2>&1; then
  echo "拉取 mongo 镜像（仅首次或镜像缺失时）..."
  run_sudo docker pull "$MONGO_IMAGE" || true
else
  echo "mongo 镜像已存在，跳过拉取."
fi
# 证书目录在 compose up 前就要就绪（compose 内 nginx 容器会挂载）
NGINX_DOMAIN="${NGINX_DOMAIN:-yuheng.yuxindazhineng.com}"
NGINX_SSL_DIR="/etc/ssl/yh_web/$NGINX_DOMAIN"
run_sudo mkdir -p "$NGINX_SSL_DIR"
if [ -f "$ROOT/nginx/$NGINX_DOMAIN.pem" ] && [ -f "$ROOT/nginx/$NGINX_DOMAIN.key" ]; then
  run_sudo cp -f "$ROOT/nginx/$NGINX_DOMAIN.pem" "$NGINX_SSL_DIR/fullchain.pem"
  run_sudo cp -f "$ROOT/nginx/$NGINX_DOMAIN.key" "$NGINX_SSL_DIR/privkey.pem"
  run_sudo chmod 644 "$NGINX_SSL_DIR/fullchain.pem"
  run_sudo chmod 600 "$NGINX_SSL_DIR/privkey.pem"
elif [ -f "$ROOT/nginx/fullchain.pem" ] && [ -f "$ROOT/nginx/privkey.pem" ]; then
  run_sudo cp -f "$ROOT/nginx/fullchain.pem" "$ROOT/nginx/privkey.pem" "$NGINX_SSL_DIR/"
  run_sudo chmod 644 "$NGINX_SSL_DIR/fullchain.pem"
  run_sudo chmod 600 "$NGINX_SSL_DIR/privkey.pem"
elif [ -f "$ROOT/nginx/$NGINX_DOMAIN/fullchain.pem" ] && [ -f "$ROOT/nginx/$NGINX_DOMAIN/privkey.pem" ]; then
  run_sudo cp -f "$ROOT/nginx/$NGINX_DOMAIN/fullchain.pem" "$ROOT/nginx/$NGINX_DOMAIN/privkey.pem" "$NGINX_SSL_DIR/"
  run_sudo chmod 644 "$NGINX_SSL_DIR/fullchain.pem"
  run_sudo chmod 600 "$NGINX_SSL_DIR/privkey.pem"
fi
compose_cmd down 2>/dev/null || true
compose_cmd up -d --force-recreate

echo ""
echo "[3/3] 证书与宿主机 Nginx（可选）..."
NGINX_CONF_NAME="${NGINX_DOMAIN}.conf"
if [ -f "$ROOT/nginx/$NGINX_CONF_NAME" ]; then
  run_sudo cp -f "$ROOT/nginx/$NGINX_CONF_NAME" /etc/nginx/conf.d/ 2>/dev/null || true
  if run_sudo nginx -t 2>/dev/null; then
    run_sudo systemctl reload nginx 2>/dev/null && echo "宿主机 Nginx 已重载." || true
  fi
fi

echo ""
echo "完成. 对外仅 443；反代: https://$NGINX_DOMAIN"
