#!/bin/bash
#
# SmartClean 一键部署脚本（Docker 版 — 本机模拟）
#
# 用法:
#   ./deploy.sh              # 构建并部署所有服务
#   ./deploy.sh web          # 仅重建部署 Web 服务
#   ./deploy.sh task         # 仅重建部署 Task 服务
#   ./deploy.sh front        # 仅重建部署前端
#   ./deploy.sh rollback     # 回滚到上一版本
#   ./deploy.sh status       # 查看容器状态
#   ./deploy.sh logs [服务名] # 查看日志
#   ./deploy.sh stop         # 停止所有容器
#   ./deploy.sh clean        # 停止并清理（含数据卷）

set -e

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

# ===== 版本号 =====
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')

BACKUP_FILE="$DEPLOY_DIR/.last-version"
CURRENT_FILE="$DEPLOY_DIR/.current-version"

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"; }

DC="docker compose -f $DEPLOY_DIR/docker-compose.yml"

# ===== 飞书通知 =====
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
}

# ===== 检查 Docker =====
check_docker() {
    if ! command -v docker &> /dev/null; then
        log_error "Docker 未安装，请先安装 Docker Desktop"
        exit 1
    fi
    if ! docker info > /dev/null 2>&1; then
        log_error "Docker 未启动，请先启动 Docker Desktop"
        exit 1
    fi
}

# ===== 备份当前版本号 =====
backup_version() {
    if [ -f "$CURRENT_FILE" ]; then
        cp "$CURRENT_FILE" "$BACKUP_FILE"
        log_info "已备份当前版本: $(cat "$BACKUP_FILE")"
    fi
}

# ===== 本地构建产物 =====
build_local() {
    local target="${1:-all}"
    local start_time=$(date +%s)

    cd "$ROOT_DIR"

    case "$target" in
        web)
            log_step "本地构建 Web 服务..."
            bash build.sh web
            ;;
        task)
            log_step "本地构建 Task 服务..."
            bash build.sh task
            ;;
        front)
            log_step "本地构建前端 (docker 模式)..."
            cd "$ROOT_DIR/frontend/witcleansystem"
            npm run build-docker
            ;;
        all)
            log_step "本地构建全部..."
            bash build.sh backend
            cd "$ROOT_DIR/frontend/witcleansystem"
            npm run build-docker
            ;;
    esac

    local elapsed=$(( $(date +%s) - start_time ))
    log_info "本地构建完成 (${elapsed}s)"
}

# ===== 打包 Docker 镜像 =====
build_images() {
    local target="${1:-all}"
    local start_time=$(date +%s)

    cd "$DEPLOY_DIR"

    case "$target" in
        web)
            log_step "打包 Web 镜像 ($VERSION)..."
            $DC build --no-cache web
            docker tag smartclean-web:latest smartclean-web:$VERSION 2>/dev/null || true
            ;;
        task)
            log_step "打包 Task 镜像 ($VERSION)..."
            $DC build --no-cache task
            docker tag smartclean-task:latest smartclean-task:$VERSION 2>/dev/null || true
            ;;
        front)
            log_step "打包前端镜像 ($VERSION)..."
            $DC build --no-cache frontend
            docker tag smartclean-front:latest smartclean-front:$VERSION 2>/dev/null || true
            ;;
        all)
            log_step "打包全部镜像 ($VERSION)..."
            $DC build --no-cache web frontend
            docker tag smartclean-web:latest smartclean-web:$VERSION 2>/dev/null || true
            docker tag smartclean-front:latest smartclean-front:$VERSION 2>/dev/null || true
            ;;
    esac

    local elapsed=$(( $(date +%s) - start_time ))
    log_info "镜像打包完成 (${elapsed}s)"
}

# ===== 部署服务 =====
deploy_services() {
    local target="${1:-all}"

    cd "$DEPLOY_DIR"

    log_step "部署应用服务..."
    case "$target" in
        web)
            $DC down 2>/dev/null || true
            $DC up -d web frontend
            ;;
        task)
            $DC up -d --no-deps task
            ;;
        front)
            $DC down 2>/dev/null || true
            $DC up -d web frontend
            ;;
        all)
            $DC down 2>/dev/null || true
            $DC up -d web frontend
            ;;
    esac

    log_info "容器已启动"
}

# ===== 健康检查 =====
healthcheck() {
    local target="${1:-all}"
    local max_retries=30
    local interval=3

    log_step "健康检查..."

    # Web 服务
    if [ "$target" = "all" ] || [ "$target" = "web" ]; then
        log_info "  检查 Web 服务 (http://localhost:$WEB_PORT)..."
        for i in $(seq 1 $max_retries); do
            if curl -sf -X POST "http://localhost:$WEB_PORT/dropDown/districtTree" > /dev/null 2>&1; then
                log_info "  Web 服务健康 (第${i}次检查通过)"
                break
            fi
            if [ $i -eq $max_retries ]; then
                log_error "  Web 服务健康检查失败"
                log_error "  查看日志: $DC logs web"
                return 1
            fi
            printf "."
            sleep $interval
        done
    fi

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

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

# ===== 回滚 =====
rollback() {
    if [ ! -f "$BACKUP_FILE" ]; then
        log_error "没有可回滚的版本"
        exit 1
    fi

    local old_version=$(cat "$BACKUP_FILE")
    log_warn "回滚到版本: $old_version"

    local has_images=true
    docker image inspect smartclean-web:$old_version > /dev/null 2>&1 || has_images=false
    docker image inspect smartclean-front:$old_version > /dev/null 2>&1 || has_images=false

    if [ "$has_images" = false ]; then
        log_error "旧版本镜像不存在 ($old_version)，无法回滚"
        exit 1
    fi

    export VERSION="$old_version"
    cd "$DEPLOY_DIR"
    $DC down 2>/dev/null || true
    $DC up -d web frontend

    echo "$old_version" > "$CURRENT_FILE"
    log_info "回滚完成"

    notify_feishu "⚠️ SmartClean 已回滚 (Docker)" \
      "**回滚版本:** $old_version\\n**触发原因:** 健康检查失败" \
      "yellow"
}

# ===== 清理旧镜像 =====
cleanup_images() {
    log_info "清理旧镜像（保留最近 5 个版本）..."
    for name in smartclean-web smartclean-task smartclean-front; do
        docker images "$name" --format "{{.Tag}}" | grep -v "latest" | sort -r | tail -n +6 | while read tag; do
            docker rmi "$name:$tag" 2>/dev/null && echo "  删除 $name:$tag"
        done
    done
}

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

case "$TARGET" in
    status)
        $DC ps
        exit 0
        ;;
    logs)
        shift
        $DC logs -f $@
        exit 0
        ;;
    stop)
        log_info "停止所有容器..."
        $DC down
        log_info "已停止"
        exit 0
        ;;
    clean)
        log_warn "停止所有容器并清理数据卷..."
        $DC down -v --rmi all
        log_info "已清理"
        exit 0
        ;;
    rollback)
        check_docker
        rollback
        exit 0
        ;;
    all|web|task|front)
        ;;
    *)
        echo "用法: $0 {all|web|task|front|rollback|status|logs|stop|clean}"
        exit 1
        ;;
esac

echo ""
log_info "======================================"
log_info "  SmartClean 自动化部署 (Docker)"
log_info "  版本:  $VERSION"
log_info "  分支:  $BRANCH"
log_info "  提交:  $COMMIT"
log_info "  目标:  $TARGET"
log_info "======================================"
echo ""

# 1. 检查 Docker
check_docker

# 2. 备份当前版本号
backup_version

# 3. 本地构建产物（Maven + npm）
build_local "$TARGET"

# 4. 打包 Docker 镜像（COPY 本地产物）
build_images "$TARGET"

# 5. 部署容器
deploy_services "$TARGET"

# 6. 健康检查
if healthcheck "$TARGET"; then
    echo "$VERSION" > "$CURRENT_FILE"
    cleanup_images

    ELAPSED=$(( $(date +%s) - DEPLOY_START ))

    echo ""
    log_info "======================================"
    log_info "  ✅ 部署成功！"
    log_info "  版本:  $VERSION"
    log_info "  耗时:  ${ELAPSED}s"
    log_info "  前端:  http://localhost:$FRONT_PORT"
    log_info "  Web:   http://localhost:$WEB_PORT"
    log_info "======================================"

    notify_feishu "✅ SmartClean 部署成功 (Docker)" \
      "**版本:** $VERSION\\n**分支:** $BRANCH\\n**提交:** $COMMIT\\n**目标:** $TARGET\\n**耗时:** ${ELAPSED}s\\n**前端:** http://localhost:$FRONT_PORT\\n**Web:** http://localhost:$WEB_PORT" \
      "green"
else
    log_error "健康检查失败，自动回滚..."
    rollback

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