#!/bin/bash

# =============================================================================
# 全栈应用构建脚本
# 
# 功能：
# 1. 构建 Next.js SSG 静态文件
# 2. 将静态文件复制到 Go 嵌入目录
# 3. 构建 Go 二进制文件，包含嵌入的前端文件
# 4. 生成多平台静态二进制文件 (Windows/macOS/Linux)
#
# 使用方法：
#   ./build-fullstack.sh
# =============================================================================

set -e

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m'

# 配置变量
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$SCRIPT_DIR"
FRONTEND_DIR="$PROJECT_ROOT/chuan-next"
FRONTEND_OUT_DIR="$FRONTEND_DIR/out"
GO_WEB_DIR="$PROJECT_ROOT/internal/web"
FRONTEND_EMBED_DIR="$GO_WEB_DIR/frontend"
DIST_DIR="$PROJECT_ROOT/dist"

# 平台配置
PLATFORMS=(
    "windows/amd64:file-transfer-server.exe"
    "darwin/amd64:file-transfer-server-macos-amd64"
    "darwin/arm64:file-transfer-server-macos-arm64"  
    "linux/amd64:file-transfer-server-linux-amd64"
    "linux/arm64:file-transfer-server-linux-arm64"
)

# 打印函数
print_header() {
    echo -e "${PURPLE}========================================${NC}"
    echo -e "${PURPLE}🚀 $1${NC}"
    echo -e "${PURPLE}========================================${NC}"
}

print_step() {
    echo -e "${BLUE}📋 $1${NC}"
}

print_success() {
    echo -e "${GREEN}✅ $1${NC}"
}

print_warning() {
    echo -e "${YELLOW}⚠️  $1${NC}"
}

print_error() {
    echo -e "${RED}❌ $1${NC}"
}

print_info() {
    echo -e "${CYAN}ℹ️  $1${NC}"
}

print_verbose() {
    echo -e "${CYAN}[INFO]${NC} $1"
}

# 检查依赖
check_dependencies() {
    print_step "检查构建依赖..."
    
    local missing_deps=()
    
    if ! command -v node &> /dev/null; then
        missing_deps+=("Node.js")
    fi
    
    if ! command -v yarn &> /dev/null; then
        missing_deps+=("Yarn")
    fi
    
    if ! command -v go &> /dev/null; then
        missing_deps+=("Go")
    fi
    
    if [ ${#missing_deps[@]} -gt 0 ]; then
        print_error "缺少必要的依赖: ${missing_deps[*]}"
        print_info "请安装缺少的依赖后重试"
        exit 1
    fi
    
    print_verbose "Node.js 版本: $(node --version)"
    print_verbose "Yarn 版本: $(yarn --version)"
    print_verbose "Go 版本: $(go version)"
    
    print_success "依赖检查完成"
}

# 清理函数
clean_all() {
    print_step "清理构建文件..."
    
    # 清理前端构建
    [ -d "$FRONTEND_DIR/.next" ] && rm -rf "$FRONTEND_DIR/.next"
    [ -d "$FRONTEND_OUT_DIR" ] && rm -rf "$FRONTEND_OUT_DIR"
    
    # 清理嵌入的前端文件
    if [ -d "$FRONTEND_EMBED_DIR" ]; then
        find "$FRONTEND_EMBED_DIR" -name "*.html" -o -name "*.js" -o -name "*.css" -o -name "*.json" -o -name "*.png" -o -name "*.jpg" -o -name "*.svg" -o -name "*.ico" | xargs rm -f 2>/dev/null || true
    fi
    
    # 清理输出目录
    [ -d "$DIST_DIR" ] && rm -rf "$DIST_DIR"
    
    print_success "清理完成"
}

# 构建前端
build_frontend() {
    print_step "构建 Next.js 前端..."
    
    if [ ! -d "$FRONTEND_DIR" ]; then
        print_error "前端目录不存在: $FRONTEND_DIR"
        exit 1
    fi
    
    cd "$FRONTEND_DIR"
    
    # 安装依赖
    print_verbose "安装前端依赖..."
    yarn install --silent
    
    # 临时移除 API 目录
    api_backup_name=""
    if [ -d "src/app/api" ]; then
        api_backup_name="next-api-backup-$(date +%s)-$$"
        mv src/app/api "/tmp/$api_backup_name" 2>/dev/null || true
        print_verbose "API 目录已备份到: /tmp/$api_backup_name"
    fi
    
    # 构建
    print_verbose "执行 SSG 构建..."
    if ! NEXT_EXPORT=true NODE_ENV=production NEXT_PUBLIC_BACKEND_URL= NEXT_PUBLIC_WS_URL= NEXT_PUBLIC_API_BASE_URL= yarn build > build.log 2>&1; then
        print_error "前端构建失败，查看 $FRONTEND_DIR/build.log"
        cat build.log
        # 恢复 API 目录后再退出
        if [ -n "$api_backup_name" ] && [ -d "/tmp/$api_backup_name" ]; then
            mv "/tmp/$api_backup_name" src/app/api 2>/dev/null || true
        fi
        exit 1
    fi
    rm -f build.log
    
    # 恢复 API 目录
    if [ -n "$api_backup_name" ] && [ -d "/tmp/$api_backup_name" ]; then
        mv "/tmp/$api_backup_name" src/app/api 2>/dev/null || true
        print_verbose "已恢复 API 目录"
    fi
    
    # 清理历史备份文件
    find /tmp -name "next-api-backup-*" -mmin +60 -exec rm -rf {} \; 2>/dev/null || true
    
    cd "$PROJECT_ROOT"
    
    # 验证构建结果
    if [ ! -d "$FRONTEND_OUT_DIR" ] || [ ! -f "$FRONTEND_OUT_DIR/index.html" ]; then
        print_error "前端构建失败：输出文件不存在"
        exit 1
    fi
    
    print_success "前端构建完成"
}

# 复制前端文件到嵌入目录
copy_frontend_files() {
    print_step "复制前端文件到嵌入目录..."
    
    mkdir -p "$FRONTEND_EMBED_DIR"
    
    # 清理现有文件（除了 .gitkeep）
    find "$FRONTEND_EMBED_DIR" -type f ! -name ".gitkeep" -delete 2>/dev/null || true
    
    # 复制所有文件
    if [ -d "$FRONTEND_OUT_DIR" ]; then
        cp -r "$FRONTEND_OUT_DIR"/* "$FRONTEND_EMBED_DIR/" 2>/dev/null || true
        
        file_count=$(find "$FRONTEND_EMBED_DIR" -type f ! -name ".gitkeep" | wc -l)
        total_size=$(du -sh "$FRONTEND_EMBED_DIR" 2>/dev/null | cut -f1 || echo "未知")
        
        print_verbose "复制了 $file_count 个文件，总大小: $total_size"
        print_success "前端文件复制完成"
    else
        print_error "前端输出目录不存在: $FRONTEND_OUT_DIR"
        exit 1
    fi
}

# 构建多平台后端
build_backend() {
    print_step "构建多平台 Go 后端..."
    
    cd "$PROJECT_ROOT"
    
    # 创建输出目录
    mkdir -p "$DIST_DIR"
    
    # 构建参数
    local ldflags="-s -w -extldflags '-static'"
    
    print_verbose "构建参数: $ldflags"
    
    # 为每个平台构建
    for platform_config in "${PLATFORMS[@]}"; do
        IFS=':' read -r platform binary_name <<< "$platform_config"
        IFS='/' read -r goos goarch <<< "$platform"
        
        output_path="$DIST_DIR/$binary_name"
        
        print_verbose "构建 $platform -> $binary_name"
        
        # 设置环境变量并构建
        if ! env CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build \
            -ldflags "$ldflags" \
            -o "$output_path" \
            ./cmd; then
            print_error "构建 $platform 失败"
            exit 1
        fi
        
        # 验证构建结果
        if [ ! -f "$output_path" ]; then
            print_error "构建验证失败: $output_path 不存在"
            exit 1
        fi
        
        binary_size=$(du -sh "$output_path" | cut -f1)
        print_verbose "✓ $binary_name ($binary_size)"
    done
    
    print_success "多平台后端构建完成"
}

# 验证最终结果
verify_build() {
    print_step "验证构建结果..."
    
    local errors=()
    
    # 检查前端嵌入文件
    if [ ! -d "$FRONTEND_EMBED_DIR" ]; then
        errors+=("前端嵌入目录不存在")
    else
        embedded_files=$(find "$FRONTEND_EMBED_DIR" -type f ! -name ".gitkeep" | wc -l)
        if [ "$embedded_files" -eq 0 ]; then
            errors+=("没有嵌入的前端文件")
        fi
    fi
    
    # 检查所有平台的二进制文件
    for platform_config in "${PLATFORMS[@]}"; do
        IFS=':' read -r platform binary_name <<< "$platform_config"
        binary_path="$DIST_DIR/$binary_name"
        
        if [ ! -f "$binary_path" ]; then
            errors+=("$platform 二进制文件不存在: $binary_name")
        fi
    done
    
    if [ ${#errors[@]} -gt 0 ]; then
        print_error "构建验证失败:"
        for error in "${errors[@]}"; do
            echo "  - $error"
        done
        exit 1
    fi
    
    print_success "构建验证通过"
}

# 显示构建摘要
show_summary() {
    print_header "构建完成"
    
    echo -e "${GREEN}🎉 多平台全栈应用构建成功！${NC}"
    echo ""
    
    print_info "� 构建输出目录: $DIST_DIR"
    
    if [ -d "$FRONTEND_EMBED_DIR" ]; then
        embedded_files=$(find "$FRONTEND_EMBED_DIR" -type f ! -name ".gitkeep" | wc -l)
        echo "   - 嵌入的前端文件: $embedded_files 个"
    fi
    
    echo ""
    print_info "� 生成的二进制文件:"
    
    for platform_config in "${PLATFORMS[@]}"; do
        IFS=':' read -r platform binary_name <<< "$platform_config"
        binary_path="$DIST_DIR/$binary_name"
        
        if [ -f "$binary_path" ]; then
            binary_size=$(du -sh "$binary_path" | cut -f1)
            echo "   ✅ $binary_name ($platform) - $binary_size"
        else
            echo "   ❌ $binary_name ($platform) - 构建失败"
        fi
    done
    
    echo ""
    print_info "� 部署说明:"
    echo "   1. 选择对应平台的二进制文件进行部署"
    echo "   2. 运行命令: ./二进制文件名"
    echo "   3. 访问地址: http://localhost:8080"
    echo ""
    print_info "🌟 特性:"
    echo "   ✅ 前端界面完全嵌入"
    echo "   ✅ 静态编译，无外部依赖"
    echo "   ✅ 支持多平台部署"
    echo "   ✅ 单文件部署"
}

# 错误处理
error_cleanup() {
    print_error "构建过程中发生错误"
    
    # 尝试恢复 API 目录
    local api_backups=$(ls /tmp/next-api-backup-*-$$ 2>/dev/null || true)
    
    if [ -n "$api_backups" ]; then
        for backup in $api_backups; do
            if [ -d "$backup" ] && [ -d "$FRONTEND_DIR" ]; then
                mv "$backup" "$FRONTEND_DIR/src/app/api" 2>/dev/null || true
                print_verbose "已恢复 API 目录: $backup"
                break
            fi
        done
    fi
    
    exit 1
}

# 主函数
main() {
    print_header "多平台全栈应用构建"
    
    # 设置错误处理
    trap error_cleanup ERR INT TERM
    
    # 执行构建步骤
    check_dependencies
    clean_all
    build_frontend
    copy_frontend_files
    build_backend
    verify_build
    show_summary
}

# 如果脚本被直接执行
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi
