#!/bin/bash
#
# SmartClean 一键部署脚本（无 Docker 版 — 部署到远程服务器）
#
# 用法:
#   ./deploy.sh              # 构建并部署所有服务
#   ./deploy.sh web          # 仅构建部署 Web 服务
#   ./deploy.sh task         # 仅构建部署 Task 服务
#   ./deploy.sh front        # 仅构建部署前端（生产包）
#   ./deploy.sh front-test   # 构建测试环境前端并部署
#   ./deploy.sh backend      # 构建部署后端（web + task）
#   ./deploy.sh rollback     # 回滚到上一版本
#   ./deploy.sh setup        # 首次初始化服务器目录
#   ./deploy.sh status       # 查看服务器服务状态

set -e

DEPLOY_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT_DIR="$(dirname "$(dirname "$DEPLOY_DIR")")"
source "$DEPLOY_DIR/config.sh"

# ===== 版本号 =====
GIT_HASH=$(cd "$ROOT_DIR" && git rev-parse --short HEAD)
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
VERSION="${TIMESTAMP}-${GIT_HASH}"
BRANCH=$(cd "$ROOT_DIR" && git rev-parse --abbrev-ref HEAD)
COMMIT=$(cd "$ROOT_DIR" && git log -1 --format='%h %s')

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

log_info()  { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn()  { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
log_step()  { echo -e "${CYAN}[STEP]${NC} $1"; }

SSH_CMD="ssh $DEPLOY_USER@$DEPLOY_HOST"
SCP_CMD="scp"

# ===== 飞书通知 =====
notify_feishu() {
    local title="$1" content="$2" color="$3"
    curl -s -X POST "$FEISHU_WEBHOOK" \
      -H "Content-Type: application/json" \
      -d "{
        \"msg_type\": \"interactive\",
        \"card\": {
          \"header\": {\"title\":{\"tag\":\"plain_text\",\"content\":\"$title\"},\"template\":\"$color\"},
          \"elements\": [{\"tag\":\"markdown\",\"content\":\"$content\"}]
        }
      }" > /dev/null 2>&1
}

# ===== 检查 SSH 连接 =====
check_ssh() {
    log_info "检查 SSH 连接 ($DEPLOY_USER@$DEPLOY_HOST)..."
    if ! $SSH_CMD "echo ok" > /dev/null 2>&1; then
        log_error "无法连接到 $DEPLOY_USER@$DEPLOY_HOST"
        log_error "请先配置 SSH 免密登录:"
        log_error "  ssh-keygen -t ed25519"
        log_error "  ssh-copy-id $DEPLOY_USER@$DEPLOY_HOST"
        exit 1
    fi
    log_info "SSH 连接正常"
}

# ===== 首次初始化服务器 =====
setup_server() {
    log_step "1/2 初始化服务器目录结构..."
    $SCP_CMD "$DEPLOY_DIR/scripts/setup.sh" "$DEPLOY_USER@$DEPLOY_HOST:/tmp/smartclean-setup.sh"
    $SSH_CMD "bash /tmp/smartclean-setup.sh && rm -f /tmp/smartclean-setup.sh"

    log_step "2/2 上传管理脚本..."
    $SCP_CMD "$DEPLOY_DIR/scripts/restart-web.sh" "$DEPLOY_USER@$DEPLOY_HOST:$REMOTE_SCRIPTS_DIR/"
    $SCP_CMD "$DEPLOY_DIR/scripts/restart-task.sh" "$DEPLOY_USER@$DEPLOY_HOST:$REMOTE_SCRIPTS_DIR/"
    $SCP_CMD "$DEPLOY_DIR/scripts/restart-front.sh" "$DEPLOY_USER@$DEPLOY_HOST:$REMOTE_SCRIPTS_DIR/"
    $SSH_CMD "chmod +x $REMOTE_SCRIPTS_DIR/*.sh"

    log_info "服务器初始化完成"
}

# ===== 查看服务器状态 =====
show_status() {
    log_info "服务器状态 ($DEPLOY_HOST):"
    $SSH_CMD bash <<'EOF'
        echo ""
        echo "===== Web 服务 (Tomcat) ====="
        TOMCAT_PID=$(ps -ef | grep "[c]atalina" | awk '{print $2}')
        if [ -n "$TOMCAT_PID" ]; then
            echo "  状态: 运行中 (PID=$TOMCAT_PID)"
        else
            echo "  状态: 未运行"
        fi

        echo ""
        echo "===== Task 服务 ====="
        if [ -f /opt/smartclean/task/task.pid ]; then
            TASK_PID=$(cat /opt/smartclean/task/task.pid)
            if kill -0 "$TASK_PID" 2>/dev/null; then
                echo "  状态: 运行中 (PID=$TASK_PID)"
            else
                echo "  状态: 未运行 (PID 文件残留)"
            fi
        else
            echo "  状态: 未运行"
        fi

        echo ""
        echo "===== Nginx ====="
        if nginx -t 2>/dev/null; then
            echo "  状态: 运行中"
        else
            echo "  状态: 异常"
        fi

        echo ""
        echo "===== 备份列表 ====="
        ls -dt /opt/smartclean/backups/*/ 2>/dev/null | head -5 || echo "  无备份"
        echo ""
EOF
}

# ===== 本地构建 =====
build_local() {
    local target="$1"
    local build_target="$target"

    # 映射 deploy 参数到 build.sh 参数
    case "$target" in
        all)        build_target="all" ;;
        web)        build_target="web" ;;
        task)       build_target="task" ;;
        backend)    build_target="backend" ;;
        front)      build_target="front" ;;
        front-test) build_target="front-test" ;;
    esac

    log_step "本地构建 (目标: $build_target)..."
    cd "$ROOT_DIR"
    bash build.sh "$build_target"

    # 验证产物
    case "$target" in
        web|backend|all)
            [ ! -f "$ROOT_DIR/$LOCAL_WAR" ] && log_error "产物不存在: $LOCAL_WAR" && exit 1
            log_info "  ROOT.war: $(du -h "$ROOT_DIR/$LOCAL_WAR" | cut -f1)"
            ;;&
        task|backend|all)
            [ ! -f "$ROOT_DIR/$LOCAL_TASK_JAR" ] && log_error "产物不存在: $LOCAL_TASK_JAR" && exit 1
            log_info "  task.jar: $(du -h "$ROOT_DIR/$LOCAL_TASK_JAR" | cut -f1)"
            ;;&
        front|front-test|all)
            [ ! -d "$ROOT_DIR/$LOCAL_FRONT_DIST" ] && log_error "产物不存在: $LOCAL_FRONT_DIST" && exit 1
            log_info "  dist/: $(du -sh "$ROOT_DIR/$LOCAL_FRONT_DIST" | cut -f1)"
            ;;
    esac

    log_info "本地构建完成"
}

# ===== 远程备份 =====
backup_remote() {
    local target="$1"
    log_step "远程备份当前版本..."

    $SSH_CMD bash <<BKEOF
        BACKUP="$REMOTE_BACKUP_DIR/$VERSION"
        mkdir -p "\$BACKUP"

        case "$target" in
            web|backend|all)
                cp "$TOMCAT_WEBAPPS/ROOT.war" "\$BACKUP/" 2>/dev/null && echo "  备份 ROOT.war" || echo "  ROOT.war 不存在，跳过"
                ;;&
            task|backend|all)
                cp "$REMOTE_TASK_DIR/task.jar" "\$BACKUP/" 2>/dev/null && echo "  备份 task.jar" || echo "  task.jar 不存在，跳过"
                ;;&
            front|front-test|all)
                if [ -d "$REMOTE_FRONT_DIR/dist" ]; then
                    cp -r "$REMOTE_FRONT_DIR/dist" "\$BACKUP/"
                    echo "  备份 front/dist"
                fi
                ;;
        esac

        # 清理过期备份
        cd "$REMOTE_BACKUP_DIR"
        TOTAL=\$(ls -dt */ 2>/dev/null | wc -l)
        if [ \$TOTAL -gt $MAX_BACKUPS ]; then
            ls -dt */ | tail -n +\$(($MAX_BACKUPS + 1)) | xargs rm -rf
            echo "  已清理过期备份，保留最近 $MAX_BACKUPS 个"
        fi
BKEOF

    log_info "远程备份完成"
}

# ===== 上传产物 =====
upload_artifacts() {
    local target="$1"
    log_step "上传构建产物..."

    case "$target" in
        web|backend|all)
            log_info "  上传 ROOT.war..."
            $SCP_CMD "$ROOT_DIR/$LOCAL_WAR" "$DEPLOY_USER@$DEPLOY_HOST:$TOMCAT_WEBAPPS/ROOT.war"
            ;;&
        task|backend|all)
            log_info "  上传 task.jar..."
            $SCP_CMD "$ROOT_DIR/$LOCAL_TASK_JAR" "$DEPLOY_USER@$DEPLOY_HOST:$REMOTE_TASK_DIR/task.jar"
            ;;&
        front|front-test|all)
            log_info "  上传前端文件..."
            $SSH_CMD "rm -rf $REMOTE_FRONT_DIR/dist"
            $SCP_CMD -r "$ROOT_DIR/$LOCAL_FRONT_DIST" "$DEPLOY_USER@$DEPLOY_HOST:$REMOTE_FRONT_DIR/dist"
            ;;
    esac

    log_info "产物上传完成"
}

# ===== 远程重启服务 =====
restart_services() {
    local target="$1"
    log_step "远程重启服务..."

    case "$target" in
        web|backend|all)
            log_info "  重启 Web 服务..."
            $SSH_CMD "bash $REMOTE_SCRIPTS_DIR/restart-web.sh"
            ;;&
        task|backend|all)
            log_info "  重启 Task 服务..."
            $SSH_CMD "bash $REMOTE_SCRIPTS_DIR/restart-task.sh $TASK_PROFILE '$TASK_JVM_OPTS'"
            ;;&
        front|front-test|all)
            log_info "  重新加载前端..."
            $SSH_CMD "bash $REMOTE_SCRIPTS_DIR/restart-front.sh"
            ;;
    esac

    log_info "服务重启完成"
}

# ===== 健康检查 =====
healthcheck() {
    local target="$1"
    log_step "健康检查..."

    # Web 服务检查
    if [ "$target" = "all" ] || [ "$target" = "web" ] || [ "$target" = "backend" ]; then
        log_info "  检查 Web 服务 ($HEALTHCHECK_URL)..."
        for i in $(seq 1 $HEALTHCHECK_RETRIES); do
            if curl -sf "$HEALTHCHECK_URL" > /dev/null 2>&1; then
                log_info "  Web 服务健康 (第${i}次检查通过)"
                break
            fi
            if [ $i -eq $HEALTHCHECK_RETRIES ]; then
                log_error "  Web 服务健康检查失败 (${HEALTHCHECK_RETRIES}次重试)"
                return 1
            fi
            printf "."
            sleep $HEALTHCHECK_INTERVAL
        done
    fi

    # 前端检查
    if [ "$target" = "all" ] || [ "$target" = "front" ] || [ "$target" = "front-test" ]; then
        log_info "  检查前端服务..."
        for i in $(seq 1 10); do
            if curl -sf "http://$DEPLOY_HOST/" > /dev/null 2>&1; then
                log_info "  前端服务健康"
                break
            fi
            if [ $i -eq 10 ]; then
                log_error "  前端服务健康检查失败"
                return 1
            fi
            sleep 2
        done
    fi

    log_info "健康检查通过"
    return 0
}

# ===== 回滚 =====
rollback() {
    log_warn "开始回滚..."

    LATEST_BACKUP=$($SSH_CMD "ls -dt $REMOTE_BACKUP_DIR/*/ 2>/dev/null | head -1 | xargs basename 2>/dev/null")

    if [ -z "$LATEST_BACKUP" ]; then
        log_error "没有可回滚的备份"
        exit 1
    fi

    log_warn "回滚到版本: $LATEST_BACKUP"

    $SSH_CMD bash <<RBEOF
        BACKUP="$REMOTE_BACKUP_DIR/$LATEST_BACKUP"

        if [ -f "\$BACKUP/ROOT.war" ]; then
            cp "\$BACKUP/ROOT.war" "$TOMCAT_WEBAPPS/ROOT.war"
            echo "  已还原 ROOT.war"
        fi

        if [ -f "\$BACKUP/task.jar" ]; then
            cp "\$BACKUP/task.jar" "$REMOTE_TASK_DIR/task.jar"
            echo "  已还原 task.jar"
        fi

        if [ -d "\$BACKUP/dist" ]; then
            rm -rf "$REMOTE_FRONT_DIR/dist"
            cp -r "\$BACKUP/dist" "$REMOTE_FRONT_DIR/dist"
            echo "  已还原 front/dist"
        fi
RBEOF

    restart_services "all"
    log_info "回滚完成 (版本: $LATEST_BACKUP)"

    notify_feishu "⚠️ SmartClean 已回滚" \
      "**回滚版本:** $LATEST_BACKUP\\n**服务器:** $DEPLOY_HOST\\n**操作人:** $(whoami)@$(hostname)" \
      "yellow"
}

# ===== 主流程 =====
TARGET="${1:-all}"
DEPLOY_START=$(date +%s)

case "$TARGET" in
    setup)
        check_ssh
        setup_server
        exit 0
        ;;
    rollback)
        check_ssh
        rollback
        exit 0
        ;;
    status)
        check_ssh
        show_status
        exit 0
        ;;
    all|web|task|backend|front|front-test)
        ;;
    *)
        echo "用法: $0 {all|web|task|backend|front|front-test|rollback|setup|status}"
        exit 1
        ;;
esac

echo ""
log_info "======================================"
log_info "  SmartClean 自动化部署 (远程服务器)"
log_info "  版本:   $VERSION"
log_info "  分支:   $BRANCH"
log_info "  提交:   $COMMIT"
log_info "  目标:   $TARGET"
log_info "  服务器: $DEPLOY_USER@$DEPLOY_HOST"
log_info "======================================"
echo ""

# 1. 检查连接
check_ssh

# 2. 本地构建
build_local "$TARGET"

# 3. 远程备份
backup_remote "$TARGET"

# 4. 上传产物
upload_artifacts "$TARGET"

# 5. 重启服务
restart_services "$TARGET"

# 6. 健康检查
if healthcheck "$TARGET"; then
    ELAPSED=$(( $(date +%s) - DEPLOY_START ))

    echo ""
    log_info "======================================"
    log_info "  ✅ 部署成功！"
    log_info "  版本: $VERSION"
    log_info "  耗时: ${ELAPSED}s"
    log_info "  前端: http://$DEPLOY_HOST"
    log_info "  Web:  http://$DEPLOY_HOST:8095"
    log_info "  Task: http://$DEPLOY_HOST:8097"
    log_info "======================================"

    notify_feishu "✅ SmartClean 部署成功" \
      "**版本:** $VERSION\\n**分支:** $BRANCH\\n**提交:** $COMMIT\\n**目标:** $TARGET\\n**服务器:** $DEPLOY_HOST\\n**耗时:** ${ELAPSED}s\\n**操作人:** $(whoami)@$(hostname)" \
      "green"
else
    log_error "健康检查失败，自动回滚..."
    rollback

    ELAPSED=$(( $(date +%s) - DEPLOY_START ))
    notify_feishu "❌ SmartClean 部署失败（已回滚）" \
      "**版本:** $VERSION\\n**分支:** $BRANCH\\n**提交:** $COMMIT\\n**服务器:** $DEPLOY_HOST\\n**耗时:** ${ELAPSED}s\\n**状态:** 健康检查失败，已自动回滚" \
      "red"
    exit 1
fi
