#!/bin/bash

# 覆盖率测试快速启动脚本
# 简化版本，适合日常使用

set -e

# 脚本目录
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"

echo "🚀 Claude Agent 覆盖率测试脚本"
echo "项目根目录: $PROJECT_ROOT"
echo ""

# 设置环境变量
export PYTHONDONTWRITEBYTECODE=1

# 进程管理变量
PYTEST_PID=""
HTML_PID=""

# 信号处理函数
cleanup_processes() {
    echo ""
    echo "🛑 收到中断信号，正在清理进程..."

    # 强制终止pytest进程
    if [ -n "$PYTEST_PID" ] && kill -0 "$PYTEST_PID" 2>/dev/null; then
        echo "⚠️  正在终止pytest进程 (PID: $PYTEST_PID)..."
        kill -TERM "$PYTEST_PID" 2>/dev/null || true
        sleep 2
        if kill -0 "$PYTEST_PID" 2>/dev/null; then
            echo "🔨 强制终止pytest进程..."
            kill -KILL "$PYTEST_PID" 2>/dev/null || true
        fi
    fi

    # 强制终止HTML报告进程
    if [ -n "$HTML_PID" ] && kill -0 "$HTML_PID" 2>/dev/null; then
        echo "⚠️  正在终止HTML报告进程 (PID: $HTML_PID)..."
        kill -TERM "$HTML_PID" 2>/dev/null || true
        sleep 1
        if kill -0 "$HTML_PID" 2>/dev/null; then
            kill -KILL "$HTML_PID" 2>/dev/null || true
        fi
    fi

    # 清理pytest子进程
    echo "🧹 清理pytest相关子进程..."
    pkill -f "python -m pytest" 2>/dev/null || true
    pkill -f "coverage" 2>/dev/null || true

    echo "✅ 进程清理完成"
    exit 130
}

# 注册信号处理器
trap cleanup_processes SIGINT SIGTERM

# 激活虚拟环境
if [ -d "$PROJECT_ROOT/venv" ]; then
    source "$PROJECT_ROOT/venv/bin/activate"
    echo "✅ 虚拟环境已激活"
else
    echo "❌ 虚拟环境不存在: $PROJECT_ROOT/venv"
    exit 1
fi

# 清理测试缓存
echo "🧹 清理测试缓存..."
find "$PROJECT_ROOT/tests" -name "*.pyc" -type f -delete 2>/dev/null || true
find "$PROJECT_ROOT/tests" -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null || true

# 解析命令行参数
DETAILED=""
HTML=false
ANALYSIS=false
TIMEOUT=180
VERBOSE=true  # 默认显示详细输出
QUIET=false
LIVE=false
SHOW_NAMES=true  # 默认显示测试用例名称

while [[ $# -gt 0 ]]; do
    case $1 in
        -d|--detailed)
            DETAILED="--cov-report=term-missing"
            shift
            ;;
        -v|--verbose)
            VERBOSE=true
            shift
            ;;
        -q|--quiet)
            VERBOSE=false
            QUIET=true
            shift
            ;;
        --live)
            VERBOSE=true
            LIVE=true
            shift
            ;;
        --names)
            VERBOSE=true
            SHOW_NAMES=true
            shift
            ;;
        -h|--html)
            HTML=true
            shift
            ;;
        -a|--analysis)
            ANALYSIS=true
            shift
            ;;
        -t|--timeout)
            if [ -z "$2" ] || [[ "$2" =~ ^--.*$ ]]; then
                echo "错误: --timeout 需要一个数字参数"
                exit 1
            fi
            TIMEOUT="$2"
            shift 2
            ;;
        --help)
            echo "使用方法: $0 [选项]"
            echo ""
            echo "选项:"
            echo "  -d, --detailed    显示详细覆盖率报告 (缺失行号)"
            echo "  -v, --verbose     显示详细测试执行过程 (文件级别)"
            echo "  -q, --quiet       静默模式，不显示测试用例详情"
            echo "  --names          显示每个测试用例名称 (默认开启)"
            echo "  --live           显示实时测试输出"
            echo "  -h, --html        生成HTML报告"
            echo "  -a, --analysis    运行模块覆盖率分析"
            echo "  -t, --timeout N   设置超时时间 (默认: 180秒)"
            echo "  --help           显示此帮助信息"
            echo ""
            echo "示例:"
            echo "  $0                     # 基本覆盖率测试 (显示测试用例名称)"
            echo "  $0 -q                  # 静默模式覆盖率测试"
            echo "  $0 -v                  # 显示文件级别进度"
            echo "  $0 --live             # 实时显示测试过程"
            echo "  $0 -d -h -a            # 全功能测试"
            exit 0
            ;;
        *)
            echo "未知选项: $1"
            echo "使用 --help 查看帮助"
            exit 1
            ;;
    esac
done

cd "$PROJECT_ROOT"

# 主要覆盖率测试
echo "🔍 运行覆盖率测试 (超时: ${TIMEOUT}s)..."

# 动态查找tests/unit下的所有测试目录
TEST_MODULES=()
declare -A found_modules=()

if [ -d "$PROJECT_ROOT/tests/unit" ]; then
    # 直接查找包含测试文件的子目录，避免包含父目录
    while IFS= read -r -d '' dir; do
        # 跳过tests/unit根目录本身
        if [ "$dir" != "$PROJECT_ROOT/tests/unit" ]; then
            # 只包含直接包含Python测试文件的目录
            if find "$dir" -maxdepth 1 -name "test_*.py" -o -name "*_test.py" | grep -q .; then
                # 获取目录名
                dir_name=$(basename "$dir")

                # 去掉test_前缀来获取模块名
                if [[ "$dir_name" == test_* ]]; then
                    module_name="${dir_name#test_}"
                else
                    module_name="$dir_name"
                fi

                # 如果这个模块还没有被添加过，或者当前目录名更规范（不带test_前缀）
                if [[ -z "${found_modules[$module_name]}" ]] || [[ "$dir_name" == "$module_name" ]]; then
                    found_modules["$module_name"]="${dir#$PROJECT_ROOT/}"
                fi
            fi
        fi
    done < <(find "$PROJECT_ROOT/tests/unit" -maxdepth 1 -mindepth 1 -type d -print0 | sort -z)

    # 将选中的目录添加到TEST_MODULES数组
    for module in "${!found_modules[@]}"; do
        TEST_MODULES+=("${found_modules[$module]}")
    done

    # 排序输出
    IFS=$'\n' TEST_MODULES=($(sort <<<"${TEST_MODULES[*]}"))

    echo "发现测试模块:"
    for module in "${TEST_MODULES[@]}"; do
        echo "  ✓ $module"
    done
    echo ""
else
    echo "❌ 测试目录不存在: $PROJECT_ROOT/tests/unit"
    exit 1
fi

# 构建pytest参数
PYTEST_ARGS=("--cov=src/claude_agent" "--cov-report=term")

if [ "$QUIET" = true ]; then
    PYTEST_ARGS+=("--tb=no" "-q")
    echo "执行命令: python -m pytest ${TEST_MODULES[*]} ${PYTEST_ARGS[*]} $DETAILED (静默模式)"
elif [ "$SHOW_NAMES" = true ]; then
    PYTEST_ARGS+=("-vv" "--tb=short")
    echo "执行命令: python -m pytest ${TEST_MODULES[*]} ${PYTEST_ARGS[*]} $DETAILED (显示测试用例名称)"
elif [ "$VERBOSE" = true ]; then
    PYTEST_ARGS+=("-v" "--tb=short")
    echo "执行命令: python -m pytest ${TEST_MODULES[*]} ${PYTEST_ARGS[*]} $DETAILED (详细模式 - 显示文件进度)"
else
    PYTEST_ARGS+=("--tb=line")
    echo "执行命令: python -m pytest ${TEST_MODULES[*]} ${PYTEST_ARGS[*]} $DETAILED (标准模式)"
fi

if [ -n "$DETAILED" ]; then
    PYTEST_ARGS+=("$DETAILED")
fi

echo ""

# 运行测试
echo "⏳ 启动覆盖率测试进程 (超时: ${TIMEOUT}s)..."

# 使用后台进程方式执行pytest，便于进程管理
python -m pytest "${TEST_MODULES[@]}" "${PYTEST_ARGS[@]}" &
PYTEST_PID=$!

echo "📊 pytest进程已启动 (PID: $PYTEST_PID)"

# 等待pytest进程完成或超时
WAIT_COUNT=0
PYTEST_RESULT=""

while [ $WAIT_COUNT -lt $TIMEOUT ]; do
    if ! kill -0 "$PYTEST_PID" 2>/dev/null; then
        # 进程已结束，获取退出码
        wait "$PYTEST_PID"
        PYTEST_RESULT=$?
        break
    fi

    sleep 1
    WAIT_COUNT=$((WAIT_COUNT + 1))

    # 每10秒显示一次进度
    if [ $((WAIT_COUNT % 10)) -eq 0 ]; then
        echo "⏱️  测试运行中... (已运行 ${WAIT_COUNT}/${TIMEOUT}s)"
    fi
done

# 检查是否超时
if [ $WAIT_COUNT -ge $TIMEOUT ]; then
    echo "⏰ 测试运行超时 (${TIMEOUT}s)，正在强制终止..."
    kill -TERM "$PYTEST_PID" 2>/dev/null || true
    sleep 3
    if kill -0 "$PYTEST_PID" 2>/dev/null; then
        echo "🔨 强制杀死pytest进程..."
        kill -KILL "$PYTEST_PID" 2>/dev/null || true
    fi
    echo "❌ 覆盖率测试超时"
    exit 1
fi

# 检查pytest结果
if [ "$PYTEST_RESULT" -eq 0 ]; then
    echo ""
    echo "✅ 覆盖率测试完成"
else
    echo ""
    echo "❌ 覆盖率测试失败 (退出码: $PYTEST_RESULT)"
    exit 1
fi

# 重置PID变量
PYTEST_PID=""

# 生成HTML报告
if [ "$HTML" = true ]; then
    echo ""
    echo "📄 生成HTML覆盖率报告..."

    # 使用后台进程方式执行HTML报告生成
    python -m pytest "${TEST_MODULES[@]}" --cov=src/claude_agent --cov-report=html:htmlcov --tb=no -q &
    HTML_PID=$!

    echo "📊 HTML报告进程已启动 (PID: $HTML_PID)"

    # 等待HTML报告进程完成或超时
    HTML_WAIT_COUNT=0
    HTML_TIMEOUT=120
    HTML_RESULT=""

    while [ $HTML_WAIT_COUNT -lt $HTML_TIMEOUT ]; do
        if ! kill -0 "$HTML_PID" 2>/dev/null; then
            # 进程已结束，获取退出码
            wait "$HTML_PID"
            HTML_RESULT=$?
            break
        fi

        sleep 1
        HTML_WAIT_COUNT=$((HTML_WAIT_COUNT + 1))

        # 每15秒显示一次进度
        if [ $((HTML_WAIT_COUNT % 15)) -eq 0 ]; then
            echo "⏱️  HTML报告生成中... (已运行 ${HTML_WAIT_COUNT}/${HTML_TIMEOUT}s)"
        fi
    done

    # 检查是否超时
    if [ $HTML_WAIT_COUNT -ge $HTML_TIMEOUT ]; then
        echo "⏰ HTML报告生成超时，正在终止..."
        kill -TERM "$HTML_PID" 2>/dev/null || true
        sleep 2
        if kill -0 "$HTML_PID" 2>/dev/null; then
            kill -KILL "$HTML_PID" 2>/dev/null || true
        fi
        echo "❌ HTML报告生成超时"
    elif [ "$HTML_RESULT" -eq 0 ]; then
        HTML_PATH="$PROJECT_ROOT/htmlcov/index.html"
        echo "✅ HTML报告生成成功: $HTML_PATH"
        echo "🌐 打开浏览器查看: file://$HTML_PATH"
    else
        echo "❌ HTML报告生成失败 (退出码: $HTML_RESULT)"
    fi

    # 重置PID变量
    HTML_PID=""
fi

# 模块分析
if [ "$ANALYSIS" = true ]; then
    echo ""
    echo "🔬 分析各模块覆盖率..."

    # 动态构建模块映射
    declare -A modules=()

    # 遍历源码目录获取所有模块
    if [ -d "$PROJECT_ROOT/src/claude_agent" ]; then
        while IFS= read -r -d '' src_dir; do
            # 获取模块名（去除路径前缀）
            module_name=$(basename "$src_dir")

            # 跳过__pycache__等目录
            if [[ "$module_name" != "__pycache__" && "$module_name" != "*.egg-info" ]]; then
                # 查找对应的测试目录
                test_dir=""

                # 尝试几种可能的测试目录命名模式
                for pattern in "tests/unit/${module_name}/" "tests/unit/test_${module_name}/" "tests/unit/${module_name}_test/"; do
                    if [ -d "$PROJECT_ROOT/$pattern" ] && find "$PROJECT_ROOT/$pattern" -maxdepth 2 -name "test_*.py" -o -name "*_test.py" | grep -q .; then
                        test_dir="$pattern"
                        break
                    fi
                done

                # 如果找到对应的测试目录，添加到映射中
                if [ -n "$test_dir" ]; then
                    modules["$module_name"]="$test_dir"
                fi
            fi
        done < <(find "$PROJECT_ROOT/src/claude_agent" -maxdepth 1 -type d -print0)
    fi

    echo "模块覆盖率汇总:"
    echo "------------------------"

    for module in "${!modules[@]}"; do
        echo -n "  $module: "

        # 构建覆盖率命令，根据模块名确定覆盖范围
        cov_target="src/claude_agent/$module"

        # 使用后台进程避免hang住
        python -m pytest "${modules[$module]}" --cov="$cov_target" --cov-report=term --tb=no -q </dev/null &
        MODULE_PID=$!

        # 等待30秒或进程完成
        MODULE_WAIT=0
        MODULE_RESULT=""
        while [ $MODULE_WAIT -lt 30 ]; do
            if ! kill -0 "$MODULE_PID" 2>/dev/null; then
                wait "$MODULE_PID"
                if [ $? -eq 0 ]; then
                    MODULE_RESULT="success"
                fi
                break
            fi
            sleep 1
            MODULE_WAIT=$((MODULE_WAIT + 1))
        done

        # 如果超时，强制终止
        if [ $MODULE_WAIT -ge 30 ]; then
            kill -TERM "$MODULE_PID" 2>/dev/null || true
            sleep 1
            if kill -0 "$MODULE_PID" 2>/dev/null; then
                kill -KILL "$MODULE_PID" 2>/dev/null || true
            fi
            echo "❌ 超时"
        elif [ "$MODULE_RESULT" = "success" ]; then
            # 重新运行获取结果（因为后台运行无法获取输出）
            result=$(python -m pytest "${modules[$module]}" --cov="$cov_target" --cov-report=term --tb=no -q 2>/dev/null | grep "TOTAL" | awk '{print $NF}')
            if [[ $result =~ [0-9]+% ]]; then
                echo "✅ $result"
            else
                echo "⚠️  无法解析覆盖率"
            fi
        else
            echo "❌ 测试失败"
        fi
    done

    # 如果没有找到任何模块，显示提示
    if [ ${#modules[@]} -eq 0 ]; then
        echo "⚠️  未找到可分析的模块"
    fi
fi

echo ""
echo "🎉 覆盖率测试脚本执行完成！"