#!/bin/bash
# 自动部署脚本 - 部署到 1Panel Docker 容器
# 设计原则：拉取式部署，只在服务器本地执行，CI 不通过 SSH 触发
# 使用方法: ./deploy.sh <deploy_package_path>
#   deploy_package_path: 部署包路径（如 /ci-artifacts/server-deploy-latest.tar.gz）

set -e

DEPLOY_PACKAGE="$1"
CONTAINER_NAME="${CONTAINER_NAME:-lunar-server}"
DEPLOY_DIR="${DEPLOY_DIR:-/opt/lunar/production}"
BACKUP_DIR="${BACKUP_DIR:-/opt/lunar/backups}"
HEALTH_URL="${HEALTH_URL:-http://localhost:8080/api/version}"

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

log_info() {
  echo -e "${GREEN}[INFO]${NC} $1"
}

log_warn() {
  echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
  echo -e "${RED}[ERROR]${NC} $1"
}

# 回滚函数：恢复 current.old 并重启容器
rollback() {
  if [ -d "$DEPLOY_DIR/current.old" ]; then
    rm -rf "$DEPLOY_DIR/current"
    mv "$DEPLOY_DIR/current.old" "$DEPLOY_DIR/current"
    docker restart "$CONTAINER_NAME" || log_error "回滚后容器重启失败，需人工介入"
    log_warn "已回滚到上一版本"
  else
    log_error "无可回滚版本，需人工介入"
  fi
}

# 检查部署包是否存在
if [ ! -f "$DEPLOY_PACKAGE" ]; then
  log_error "部署包不存在: $DEPLOY_PACKAGE"
  exit 1
fi

log_info "开始自动部署..."
log_info "部署包: $DEPLOY_PACKAGE"
log_info "目标容器: $CONTAINER_NAME"
log_info "部署目录: $DEPLOY_DIR"

# 创建必要的目录
mkdir -p "$DEPLOY_DIR"
mkdir -p "$BACKUP_DIR"

# 备份当前版本
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/backup_${TIMESTAMP}.tar.gz"

if [ -d "$DEPLOY_DIR/current" ]; then
  log_info "备份当前版本到: $BACKUP_FILE"
  tar -czf "$BACKUP_FILE" -C "$DEPLOY_DIR" current/ || log_warn "备份失败，继续部署"
fi

# 解压新版本到暂存目录（不碰 current，避免部署空窗）
log_info "解压部署包..."
TEMP_DIR=$(mktemp -d)
tar -xzf "$DEPLOY_PACKAGE" -C "$TEMP_DIR"

# 检查解压后的目录结构
if [ ! -d "$TEMP_DIR/deploy" ]; then
  log_error "部署包结构错误：缺少 deploy 目录"
  rm -rf "$TEMP_DIR"
  exit 1
fi

# 校验二进制存在
if [ ! -f "$TEMP_DIR/deploy/bin/server" ]; then
  log_error "部署包缺少 bin/server 二进制"
  rm -rf "$TEMP_DIR"
  exit 1
fi
chmod +x "$TEMP_DIR/deploy/bin/server"

# 部署新版本（目录级交换，接近原子）
log_info "部署新版本..."
mv "$TEMP_DIR/deploy" "$DEPLOY_DIR/current.new"
rm -rf "$DEPLOY_DIR/current.old"
if [ -d "$DEPLOY_DIR/current" ]; then
  mv "$DEPLOY_DIR/current" "$DEPLOY_DIR/current.old"
fi
mv "$DEPLOY_DIR/current.new" "$DEPLOY_DIR/current"
rm -rf "$TEMP_DIR"

# 检查 Docker 容器是否存在
if ! docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
  log_error "Docker 容器不存在: $CONTAINER_NAME"
  log_info "请在 1Panel 中创建容器，或使用以下命令："
  echo ""
  echo "docker run -d \\"
  echo "  --name $CONTAINER_NAME \\"
  echo "  -v $DEPLOY_DIR/current:/app \\"
  echo "  -p 8080:8080 \\"
  echo "  --restart unless-stopped \\"
  echo "  golang:1.22-bookworm \\"
  echo "  /app/bin/server"
  echo ""
  exit 1
fi

# 重启 Docker 容器
log_info "重启 Docker 容器: $CONTAINER_NAME"
if docker restart "$CONTAINER_NAME"; then
  log_info "✅ 容器重启成功"
else
  log_error "❌ 容器重启失败，回滚到上一版本"
  rollback
  exit 1
fi

# 健康检查：轮询 HTTP 接口确认服务真正可用
log_info "执行健康检查: $HEALTH_URL"
HEALTHY=0
for i in $(seq 1 10); do
  sleep 2
  if curl -fsS --max-time 5 "$HEALTH_URL" > /dev/null 2>&1; then
    HEALTHY=1
    break
  fi
done

if [ "$HEALTHY" = "1" ]; then
  log_info "✅ 健康检查通过"
  curl -fsS --max-time 5 "$HEALTH_URL" && echo ""
  rm -rf "$DEPLOY_DIR/current.old"
else
  log_error "❌ 健康检查失败，回滚到上一版本"
  docker logs --tail 50 "$CONTAINER_NAME" || true
  rollback
  exit 1
fi

# 清理旧备份（保留最近 5 个）
log_info "清理旧备份..."
ls -t "$BACKUP_DIR"/backup_*.tar.gz 2>/dev/null | tail -n +6 | xargs -r rm -f

log_info "✅ 部署完成！"
log_info "备份文件: $BACKUP_FILE"
log_info "部署目录: $DEPLOY_DIR/current"

# 输出部署信息（用于通知）
echo ""
echo "DEPLOY_SUCCESS=true"
echo "DEPLOY_TIME=$TIMESTAMP"
echo "CONTAINER_NAME=$CONTAINER_NAME"
