#!/bin/bash
# BuildKit 离线构建脚本 v2 - 增强版
# Usage: ./build-offline-v2.sh [cache-dir] [version]

set -e

CACHE_DIR="${1:-./build-cache}"
VERSION="${2:-latest}"
BUILDKIT_CACHE_DIR="$CACHE_DIR/buildkit"
IMAGES_DIR="$CACHE_DIR/images"
RESOURCES_DIR="$CACHE_DIR/resources"

# 颜色输出
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"
}

# 检查缓存目录
if [ ! -d "$CACHE_DIR" ]; then
    log_error "缓存目录 $CACHE_DIR 不存在"
    log_info "请先解压缓存包: tar -xzf build-cache-*.tar.gz"
    exit 1
fi

# 确保 buildx 构建器存在（使用 docker 驱动以支持本地镜像）
setup_buildx() {
    log_info "设置 BuildKit 构建器..."
    
    # 删除旧的构建器
    if docker buildx inspect offline-builder > /dev/null 2>&1; then
        docker buildx rm offline-builder 2>/dev/null || true
    fi
    
    # 创建新的构建器，使用 docker 驱动（支持本地镜像，不需要推送到 registry）
    docker buildx create --name offline-builder \
        --driver docker-container \
        --driver-opt image=moby/buildkit:buildx-stable-1 \
        --use
    
    log_info "BuildKit 构建器创建完成"
}

# 加载基础镜像
load_base_images() {
    log_info "加载基础镜像..."
    
    if [ ! -f "$IMAGES_DIR/base-images.tar" ]; then
        log_warn "基础镜像文件不存在: $IMAGES_DIR/base-images.tar"
        log_info "检查本地是否存在所需镜像..."
        
        # 检查关键镜像是否存在
        required_images=(
            "maven:3-eclipse-temurin-21"
            "eclipse-temurin:21-jdk"
            "mysql:8"
            "node:20-alpine"
            "nginx:1.29"
        )
        
        for img in "${required_images[@]}"; do
            if ! docker inspect "$img" > /dev/null 2>&1; then
                log_error "缺少基础镜像: $img"
                log_info "请确保基础镜像已加载: docker load -i base-images.tar"
                exit 1
            fi
        done
        
        log_info "本地基础镜像检查通过"
        return
    fi
    
    log_info "从 $IMAGES_DIR/base-images.tar 加载基础镜像..."
    docker load -i "$IMAGES_DIR/base-images.tar"
    log_info "基础镜像加载完成"
}

# 验证镜像是否存在
verify_image() {
    local image_name=$1
    if docker inspect "$image_name" > /dev/null 2>&1; then
        return 0
    else
        return 1
    fi
}

# 离线构建函数
offline_build() {
    local service_name=$1
    local image_name=$2
    local dockerfile=$3
    local cache_file="$BUILDKIT_CACHE_DIR/${service_name}-cache"
    
    log_info "----------------------------------------"
    log_info "构建 [$service_name] -> $image_name:$VERSION"
    log_info "----------------------------------------"
    
    if [ ! -d "$cache_file" ]; then
        log_warn "$service_name 的缓存不存在，跳过..."
        return 0
    fi
    
    # 获取 Dockerfile 中的基础镜像
    local base_images
    base_images=$(grep -E '^FROM' "$dockerfile" | awk '{print $2}' | sort -u)
    
    log_info "检查基础镜像..."
    for base_img in $base_images; do
        # 跳过多阶段构建中的 AS 别名
        base_img=$(echo "$base_img" | cut -d':' -f1-2 | sed 's/AS.*//i' | tr -d ' ')
        
        if [ -z "$base_img" ] || [[ "$base_img" == *"AS"* ]]; then
            continue
        fi
        
        if verify_image "$base_img"; then
            log_info "  ✓ $base_img"
        else
            log_warn "  ✗ $base_img (未找到)"
            # 尝试从 base-images.tar 中加载
            if [ -f "$IMAGES_DIR/base-images.tar" ]; then
                log_info "  尝试从 tar 包加载..."
                docker load -i "$IMAGES_DIR/base-images.tar" 2>/dev/null || true
            fi
        fi
    done
    
    # 执行离线构建
    log_info "开始构建..."
    
    # 构建参数
    local build_args=()
    
    # 为需要外部资源的服务添加 build-arg
    case "$service_name" in
        runtime|deer-flow-backend|deer-flow-frontend)
            if [ -d "$RESOURCES_DIR" ]; then
                build_args+=("--build-arg" "RESOURCES_DIR=$RESOURCES_DIR")
            fi
            ;;
        backend-python)
            if [ -d "$RESOURCES_DIR" ]; then
                build_args+=("--build-arg" "RESOURCES_DIR=$RESOURCES_DIR")
                build_args+=("--build-arg" "DATAX_LOCAL_PATH=$RESOURCES_DIR/DataX")
            fi
            ;;
    esac
    
    # 执行构建
    if docker buildx build \
        --builder offline-builder \
        --cache-from "type=local,src=$cache_file" \
        --pull=false \
        --output "type=docker" \
        "${build_args[@]}" \
        -f "$dockerfile" \
        -t "$image_name:$VERSION" \
        . 2>&1; then
        
        log_info "✓ $service_name 构建成功"
        return 0
    else
        log_error "✗ $service_name 构建失败"
        return 1
    fi
}

# 主流程
main() {
    log_info "======================================"
    log_info "BuildKit 离线构建"
    log_info "======================================"
    log_info "缓存目录: $CACHE_DIR"
    log_info "版本: $VERSION"
    
    # 步骤 1: 设置构建器
    setup_buildx
    
    # 步骤 2: 加载基础镜像
    load_base_images
    
    # 步骤 3: 定义服务列表
    declare -A SERVICES=(
        ["database"]="datamate-database:scripts/images/database/Dockerfile"
        ["gateway"]="datamate-gateway:scripts/images/gateway/Dockerfile"
        ["backend"]="datamate-backend:scripts/images/backend/Dockerfile"
        ["frontend"]="datamate-frontend:scripts/images/frontend/Dockerfile"
        ["runtime"]="datamate-runtime:scripts/images/runtime/Dockerfile"
        ["backend-python"]="datamate-backend-python:scripts/images/backend-python/Dockerfile"
        ["deer-flow-backend"]="deer-flow-backend:scripts/images/deer-flow-backend/Dockerfile"
        ["deer-flow-frontend"]="deer-flow-frontend:scripts/images/deer-flow-frontend/Dockerfile"
        ["mineru"]="datamate-mineru:scripts/images/mineru/Dockerfile"
    )
    
    # 步骤 4: 批量构建
    log_info ""
    log_info "======================================"
    log_info "开始批量构建"
    log_info "======================================"
    
    local failed=()
    local succeeded=()
    
    for service_name in "${!SERVICES[@]}"; do
        IFS=':' read -r image_name dockerfile <<< "${SERVICES[$service_name]}"
        
        if offline_build "$service_name" "$image_name" "$dockerfile"; then
            succeeded+=("$service_name")
        else
            failed+=("$service_name")
        fi
        echo ""
    done
    
    # 步骤 5: 汇总结果
    log_info "======================================"
    log_info "构建完成"
    log_info "======================================"
    
    if [ ${#succeeded[@]} -gt 0 ]; then
        log_info "成功 (${#succeeded[@]}): ${succeeded[*]}"
    fi
    
    if [ ${#failed[@]} -gt 0 ]; then
        log_error "失败 (${#failed[@]}): ${failed[*]}"
        exit 1
    else
        log_info "✓ 所有服务构建成功！"
        echo ""
        log_info "镜像列表:"
        docker images --format "table {{.Repository}}:{{.Tag}}\t{{.Size}}" | grep -E "(datamate-|deer-flow-)" || true
    fi
}

# 执行主流程
main "$@"
