#!/bin/bash

# DC-TOM 本地 CI 测试脚本
# 模拟 GitLab CI 流程，在本地环境运行测试并生成报告
# 注意：此脚本不会重新安装依赖，请确保已安装项目依赖
# 使用方法: ./local-ci.sh [basic|full|business|data]

set -e  # 遇到错误立即退出

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

# 项目配置
PROJECT_NAME="DC-TOM dctomproject"
BUILD_DIR="dist"
REPORTS_DIR="cypress/reports"
PUBLIC_DIR="public"
VITE_PORT="3000"
MAX_REPORTS_TO_KEEP=3  # 保留最近的报告数量

# 日志函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

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

# 检查依赖
check_dependencies() {
    log_info "检查本地环境依赖..."
    
    # 检查 Node.js
    if ! command -v node &> /dev/null; then
        log_error "Node.js 未安装，请先安装 Node.js 18+"
        exit 1
    fi
    
    local node_version=$(node -v | sed 's/v//')
    log_info "Node.js 版本: $node_version"
    
    # 检查 npm
    if ! command -v npm &> /dev/null; then
        log_error "npm 未安装"
        exit 1
    fi
    
    # 检查项目文件
    if [ ! -f "package.json" ]; then
        log_error "请在项目根目录运行此脚本"
        exit 1
    fi
    
    # 检查项目依赖（可选）
    if [ ! -d "node_modules" ]; then
        log_warning "未检测到 node_modules 目录"
        log_info "提示：如果构建失败，请先运行 'npm install' 安装依赖"
    else
        log_info "检测到 node_modules 目录，依赖已存在"
    fi
    
    log_success "环境检查通过"
}

# 构建阶段
build_stage() {
    log_info "==================== 构建阶段 ===================="
    log_info "开始构建 $PROJECT_NAME ..."
    
    # 检查是否已安装依赖
    if [ ! -d "node_modules" ]; then
        log_warning "未检测到 node_modules 目录，请先运行 'npm install' 安装依赖"
        log_info "提示：你可以运行以下命令安装依赖："
        echo "  npm install"
        exit 1
    fi
    
    log_info "检测到 node_modules 目录，跳过依赖安装"
    
    # 构建项目
    log_info "构建生产版本..."
    npm run build
    
    if [ -d "$BUILD_DIR" ]; then
        log_success "构建完成，生成 $BUILD_DIR 目录"
    else
        log_error "构建失败，未生成 $BUILD_DIR 目录"
        exit 1
    fi
}

# 启动应用服务器
start_server() {
    log_info "启动应用服务器..."
    
    # 启动预览服务器
    npm run preview -- --host 0.0.0.0 --port $VITE_PORT &
    SERVER_PID=$!
    
    log_info "等待服务器启动..."
    sleep 15
    
    # 健康检查
    local max_attempts=15
    local attempt=1
    
    while [ $attempt -le $max_attempts ]; do
        if curl -s -f http://localhost:$VITE_PORT > /dev/null; then
            log_success "应用服务器启动成功 (端口: $VITE_PORT)"
            return 0
        fi
        
        log_info "等待应用启动... (尝试 $attempt/$max_attempts)"
        sleep 3
        ((attempt++))
    done
    
    log_error "应用服务器启动失败"
    kill $SERVER_PID 2>/dev/null || true
    exit 1
}

# 停止服务器
stop_server() {
    if [ ! -z "$SERVER_PID" ]; then
        log_info "停止应用服务器..."
        kill $SERVER_PID 2>/dev/null || true
        wait $SERVER_PID 2>/dev/null || true
        log_success "服务器已停止"
    fi
}

# 清理历史报告，保留最近的 N 次测试结果
cleanup_old_reports() {
    local keep_count=${1:-$MAX_REPORTS_TO_KEEP}
    
    log_info "清理历史测试报告，保留最近 $keep_count 次结果..."
    
    # 清理 cypress/reports 目录中的历史报告
    if [ -d "$REPORTS_DIR" ]; then
        log_info "清理 $REPORTS_DIR 目录..."
        
        # 清理 HTML 报告文件（按时间戳排序）
        local html_files=($REPORTS_DIR/mochawesome_*.html)
        if [ ${#html_files[@]} -gt 0 ] && [ -f "${html_files[0]}" ]; then
            log_info "发现 ${#html_files[@]} 个 HTML 报告文件"
            
            # 按文件修改时间排序，保留最新的
            printf '%s\n' "${html_files[@]}" | xargs ls -t | tail -n +$((keep_count + 1)) | while read file; do
                log_info "删除旧 HTML 报告: $(basename "$file")"
                rm -f "$file"
            done
        fi
        
        # 清理 JSON 报告文件
        local json_files=($REPORTS_DIR/mochawesome_*.json)
        if [ ${#json_files[@]} -gt 0 ] && [ -f "${json_files[0]}" ]; then
            log_info "发现 ${#json_files[@]} 个 JSON 报告文件"
            
            printf '%s\n' "${json_files[@]}" | xargs ls -t | tail -n +$((keep_count + 1)) | while read file; do
                log_info "删除旧 JSON 报告: $(basename "$file")"
                rm -f "$file"
            done
        fi
    fi
    
    # 清理测试视频
    if [ -d "cypress/videos" ]; then
        log_info "清理测试视频..."
        
        local video_files=(cypress/videos/*.mp4)
        if [ ${#video_files[@]} -gt 0 ] && [ -f "${video_files[0]}" ]; then
            log_info "发现 ${#video_files[@]} 个视频文件"
            
            printf '%s\n' "${video_files[@]}" | xargs ls -t | tail -n +$((keep_count + 1)) | while read file; do
                log_info "删除旧视频: $(basename "$file")"
                rm -f "$file"
            done
        fi
    fi
    
    # 清理截图目录（按目录修改时间）
    if [ -d "cypress/screenshots" ]; then
        log_info "清理失败截图..."
        
        # 获取所有截图子目录
        local screenshot_dirs=(cypress/screenshots/*/)
        if [ ${#screenshot_dirs[@]} -gt 0 ] && [ -d "${screenshot_dirs[0]}" ]; then
            log_info "发现 ${#screenshot_dirs[@]} 个截图目录"
            
            printf '%s\n' "${screenshot_dirs[@]}" | xargs ls -td | tail -n +$((keep_count + 1)) | while read dir; do
                log_info "删除旧截图目录: $(basename "$dir")"
                rm -rf "$dir"
            done
        fi
    fi
    
    log_success "历史报告清理完成，保留最近 $keep_count 次测试结果"
}

# 运行 Cypress 测试
run_cypress_tests() {
    local test_type=$1
    local test_name=$2
    local spec_pattern=$3
    
    log_info "==================== $test_name ===================="
    log_info "开始运行 $test_name ..."
    
    # 清理历史报告（在测试运行前）
    cleanup_old_reports
    
    # 创建报告目录
    mkdir -p "$REPORTS_DIR/$test_type"
    
    # 运行 Cypress 测试
    npx cypress run \
        --browser chrome \
        --headless \
        --spec "$spec_pattern" \
        --config video=true,screenshotOnRunFailure=true \
        --reporter mochawesome \
        --reporter-options "reportDir=$REPORTS_DIR/$test_type,overwrite=false,html=true,json=true,timestamp=mmddyyyy_HHMMss" \
        || {
            log_warning "$test_name 部分测试失败，但继续执行"
        }
    
    log_info "$test_name 完成"
    
    # 显示生成的文件
    if [ -d "$REPORTS_DIR/$test_type" ]; then
        log_info "测试报告生成在: $REPORTS_DIR/$test_type/"
        ls -la "$REPORTS_DIR/$test_type/" || echo "报告目录为空"
    fi
    
    if [ -d "cypress/videos" ]; then
        log_info "测试视频保存在: cypress/videos/"
        ls -la cypress/videos/ || echo "视频目录为空"
    fi
    
    if [ -d "cypress/screenshots" ]; then
        log_info "失败截图保存在: cypress/screenshots/"
        ls -la cypress/screenshots/ || echo "截图目录为空"
    fi
}

# 基础测试
basic_tests() {
    run_cypress_tests "basic" "基础测试 (spec)" "cypress/e2e/spec.cy.js"
}

# 完整测试
full_tests() {
    run_cypress_tests "full" "完整测试套件 (spec)" "cypress/e2e/spec.cy.js"
}

# 生成测试报告
generate_reports() {
    log_info "==================== 生成测试报告 ===================="
    log_info "开始合并测试报告..."
    
    # 确保有全局的报告生成工具
    if ! command -v mochawesome-merge &> /dev/null; then
        log_info "安装报告生成工具..."
        npm install -g mochawesome-merge mochawesome-report-generator
    fi
    
    # 创建公共目录
    mkdir -p "$PUBLIC_DIR/reports"
    mkdir -p "$PUBLIC_DIR/assets"
    
    # 检查报告文件
    log_info "检查生成的报告文件..."
    find "$REPORTS_DIR" -name "*.json" | head -10
    
    # 合并所有测试报告
    log_info "合并测试报告..."
    if find "$REPORTS_DIR" -name "*.json" | grep -q .; then
        mochawesome-merge "$REPORTS_DIR/**/*.json" > "$PUBLIC_DIR/reports/merged-report.json" || {
            log_warning "报告合并失败，生成空报告"
            echo '{"stats":{"suites":0,"tests":0,"passes":0,"pending":0,"failures":0},"results":[]}' > "$PUBLIC_DIR/reports/merged-report.json"
        }
    else
        log_warning "未找到JSON报告文件，生成空报告"
        echo '{"stats":{"suites":0,"tests":0,"passes":0,"pending":0,"failures":0},"results":[]}' > "$PUBLIC_DIR/reports/merged-report.json"
    fi
    
    # 生成HTML报告
    log_info "生成HTML报告..."
    marge "$PUBLIC_DIR/reports/merged-report.json" \
        --reportDir "$PUBLIC_DIR/reports" \
        --inline \
        --reportTitle "DC-TOM Cypress 本地测试报告" || {
            log_warning "HTML报告生成失败"
        }
    
    # 提取统计信息
    log_info "提取测试统计信息..."
    if [ -f "./extract-stats.sh" ]; then
        ./extract-stats.sh analyze > /dev/null 2>&1 || {
            log_warning "统计信息提取失败"
        }
    else
        log_warning "统计提取脚本不存在"
    fi
    
    # 生成分类报告
    log_info "生成分类测试报告..."
    for test_dir in "$REPORTS_DIR"/*; do
        if [ -d "$test_dir" ]; then
            test_type=$(basename "$test_dir")
            log_info "处理 $test_type 测试报告..."
            
            # 合并该类型的所有报告
            if find "$test_dir" -name "*.json" | grep -q .; then
                mochawesome-merge "$test_dir/*.json" > "$PUBLIC_DIR/reports/${test_type}-report.json" 2>/dev/null || {
                    log_warning "$test_type 报告合并失败"
                    continue
                }
                
                # 生成该类型HTML报告
                marge "$PUBLIC_DIR/reports/${test_type}-report.json" \
                    --reportDir "$PUBLIC_DIR/reports/$test_type" \
                    --inline \
                    --reportTitle "DC-TOM $test_type 测试报告" 2>/dev/null || {
                        log_warning "$test_type HTML报告生成失败"
                    }
            fi
        fi
    done
    
    # 复制媒体文件
    log_info "复制媒体文件..."
    if [ -d "cypress/videos" ]; then
        cp -r cypress/videos "$PUBLIC_DIR/assets/" 2>/dev/null || echo "无视频文件"
    fi
    if [ -d "cypress/screenshots" ]; then
        cp -r cypress/screenshots "$PUBLIC_DIR/assets/" 2>/dev/null || echo "无截图文件"
    fi
    
    # 生成索引页面
    log_info "生成报告索引页面..."
    if [ -f "report-template.html" ]; then
        # 复制报告模板
        cp "report-template.html" "$PUBLIC_DIR/index.html"
        
        # 如果存在统计数据文件，将其嵌入到HTML中
        if [ -f "$PUBLIC_DIR/test-stats.json" ]; then
            log_info "嵌入统计数据到报告模板..."
            
            # 读取统计数据并转义特殊字符
            stats_json=$(cat "$PUBLIC_DIR/test-stats.json" | sed 's/"/\\"/g' | tr -d '\n\r')
            
            # 替换HTML中的内嵌数据占位符
            sed -i.bak "s|<!-- 这里可以通过服务器端或构建脚本注入真实的统计数据 -->|$stats_json|g" "$PUBLIC_DIR/index.html"
            
            # 删除备份文件
            rm -f "$PUBLIC_DIR/index.html.bak"
            
            log_success "统计数据已嵌入到报告模板"
        else
            log_warning "统计数据文件不存在，使用默认模板"
        fi
        
        log_success "使用增强型报告模板"
    else
        log_warning "未找到报告模板，使用默认模板"
        cat > "$PUBLIC_DIR/index.html" << 'EOF'
<!DOCTYPE html>
<html>
<head>
    <title>DC-TOM 本地测试报告</title>
    <meta charset="utf-8">
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; background-color: #f5f5f5; }
        .header { text-align: center; margin-bottom: 30px; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        .container { max-width: 800px; margin: 0 auto; }
        .links { list-style: none; padding: 0; }
        .links li { margin: 15px 0; background: white; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        .links a { text-decoration: none; color: #007cba; font-size: 18px; display: block; padding: 20px; border-radius: 8px; transition: background-color 0.2s; }
        .links a:hover { background-color: #f0f8ff; text-decoration: none; }
        .icon { margin-right: 10px; font-size: 20px; }
        .description { color: #666; font-size: 14px; margin-top: 5px; }
        .local-note { background: #fff3cd; color: #856404; padding: 15px; border-radius: 8px; margin-bottom: 20px; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🧪 DC-TOM Cypress 本地测试报告</h1>
            <p><strong>项目:</strong> dctomproject | <strong>环境:</strong> 本地开发</p>
            <p><strong>生成时间:</strong> <script>document.write(new Date().toLocaleString());</script></p>
        </div>
        <div class="local-note">
            <strong>📝 本地测试说明:</strong> 此报告由本地 CI 脚本生成，用于在 GitLab Runner 不可用时进行测试验证。
        </div>
        <ul class="links">
            <li>
                <a href="reports/merged-report.html">
                    <span class="icon">📊</span>完整测试报告
                    <div class="description">查看详细的测试执行结果、通过率统计和失败原因分析</div>
                </a>
            </li>
            <li>
                <a href="reports/basic/">
                    <span class="icon">🔧</span>基础功能测试
                    <div class="description">spec.cy.js 测试文件的执行结果</div>
                </a>
            </li>
            <li>
                <a href="assets/videos/">
                    <span class="icon">🎥</span>测试执行视频
                    <div class="description">观看完整的测试执行过程录像</div>
                </a>
            </li>
            <li>
                <a href="assets/screenshots/">
                    <span class="icon">📸</span>失败截图
                    <div class="description">查看测试失败时的页面截图，便于问题定位</div>
                </a>
            </li>
        </ul>
    </div>
</body>
</html>
EOF
    fi
    
    log_success "测试报告生成完成!"
    log_info "报告位置: $PUBLIC_DIR/"
    ls -la "$PUBLIC_DIR/"
}

# 打开测试报告
open_report() {
    local report_file="$PUBLIC_DIR/index.html"
    
    if [ -f "$report_file" ]; then
        log_success "正在打开测试报告..."
        
        # 根据操作系统选择打开方式
        if command -v open &> /dev/null; then
            # macOS
            open "$report_file"
        elif command -v xdg-open &> /dev/null; then
            # Linux
            xdg-open "$report_file"
        elif command -v start &> /dev/null; then
            # Windows
            start "$report_file"
        else
            log_info "请手动打开: $(pwd)/$report_file"
        fi
    else
        log_error "测试报告文件不存在: $report_file"
    fi
}

# 清理函数
cleanup() {
    log_info "清理资源..."
    stop_server
}

# 设置清理陷阱
trap cleanup EXIT INT TERM

# 显示使用说明
show_usage() {
    echo "用法: $0 [test_type]"
    echo ""
    echo "测试类型:"
    echo "  basic     - 基础测试 (spec)"
    echo "  full      - 完整测试套件 (spec)"
    echo "  all       - 运行所有测试类型 (默认)"
    echo "  cleanup   - 只清理历史报告，不运行测试"
    echo ""
    echo "使用前提:"
    echo "  - 请确保已运行 'npm install' 安装项目依赖"
    echo "  - 请在项目根目录下运行此脚本"
    echo ""
    echo "示例:"
    echo "  npm install     # 先安装依赖"
    echo "  $0 basic    # 只运行基础测试"
    echo "  $0 full     # 运行完整测试"
    echo "  $0 cleanup  # 只清理历史报告"
    echo "  $0          # 运行所有测试"
    echo ""
    echo "清理策略:"
    echo "  - 自动保留最近 $MAX_REPORTS_TO_KEEP 次测试结果"
    echo "  - 清理内容包括: HTML/JSON 报告、测试视频、失败截图"
}

# 主函数
main() {
    local test_type=${1:-"all"}
    
    echo "========================================"
    echo "  DC-TOM 本地 CI 测试脚本"
    echo "========================================"
    echo ""
    
    case $test_type in
        "help"|"-h"|"--help")
            show_usage
            exit 0
            ;;
        "cleanup")
            log_info "清理模式: 只清理历史报告"
            cleanup_old_reports
            log_success "清理完成!"
            exit 0
            ;;
        "basic"|"full"|"all")
            ;;
        *)
            log_error "未知的测试类型: $test_type"
            show_usage
            exit 1
            ;;
    esac
    
    # 执行流程
    check_dependencies
    build_stage
    start_server
    
    # 运行指定的测试
    case $test_type in
        "basic")
            basic_tests
            ;;
        "full")
            full_tests
            ;;
        "all")
            basic_tests
            full_tests
            ;;
    esac
    
    # 生成报告
    generate_reports
    
    # 打开报告
    open_report
    
    log_success "本地 CI 测试完成!"
    echo ""
    echo "🎉 测试报告已生成并打开!"
    echo "📂 报告文件位置: $(pwd)/$PUBLIC_DIR/"
    echo "🌐 主报告文件: $(pwd)/$PUBLIC_DIR/index.html"
}

# 运行主函数
main "$@"