#!/bin/bash

# KernelSU Module Test Tool
# 模块测试工具 - 在开发环境中测试模块功能

set -euo pipefail

# 配置
TEST_DIR="/tmp/ksm-test"
MOUNT_POINT="/tmp/ksm-mount"
SIMULATOR_MODE="false"

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

# 日志函数
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"
}

log_debug() {
    if [ "${DEBUG:-0}" = "1" ]; then
        echo -e "${PURPLE}[DEBUG]${NC} $1"
    fi
}

# 显示帮助
show_help() {
    cat << EOF
KernelSU Module Test Tool - 模块测试工具

用法: ksm-test [选项] <模块目录>

选项:
    -s, --simulate          模拟器模式 (不需要root权限)
    -d, --debug             启用调试输出
    -c, --clean             清理测试环境
    -l, --list-tests        列出可用的测试项目
    -t, --test <name>       运行特定测试
    -a, --all-tests         运行所有测试
    -o, --output <dir>      指定测试输出目录
    -v, --verbose           详细输出
    -h, --help              显示此帮助信息

测试项目:
    structure           - 测试模块结构
    syntax              - 测试脚本语法
    permissions         - 测试权限设置
    install             - 测试安装过程
    scripts             - 测试脚本执行
    webui               - 测试WebUI功能
    compatibility       - 测试兼容性
    security            - 安全性检查

示例:
    ksm-test ./my_module
    ksm-test --simulate --test structure ./my_module
    ksm-test -a -v ./my_module

环境变量:
    KSM_TEST_MODE       - 测试模式 (strict/normal/lenient)
    KSM_TEST_TIMEOUT    - 测试超时时间 (秒)
    DEBUG              - 启用调试模式 (1/0)
EOF
}

# 错误处理
error_exit() {
    log_error "$1"
    cleanup
    exit 1
}

# 清理函数
cleanup() {
    if [ -d "$TEST_DIR" ]; then
        rm -rf "$TEST_DIR" 2>/dev/null || true
    fi
    if mountpoint -q "$MOUNT_POINT" 2>/dev/null; then
        umount "$MOUNT_POINT" 2>/dev/null || true
    fi
    if [ -d "$MOUNT_POINT" ]; then
        rmdir "$MOUNT_POINT" 2>/dev/null || true
    fi
}

# 初始化测试环境
init_test_env() {
    local module_dir="$1"
    
    log_info "初始化测试环境..."
    
    # 创建测试目录
    mkdir -p "$TEST_DIR"
    mkdir -p "$MOUNT_POINT"
    
    # 复制模块到测试目录
    cp -r "$module_dir" "$TEST_DIR/module"
    
    # 设置环境变量
    export MODDIR="$TEST_DIR/module"
    export MODPATH="$TEST_DIR/module"
    export KSU="true"
    export KSU_VER="v0.7.0"
    export KSU_VER_CODE="10700"
    export BOOTMODE="true"
    export API="$(getprop ro.build.version.sdk 2>/dev/null || echo '30')"
    export ARCH="$(uname -m)"
    export IS64BIT="$([ "$(getprop ro.product.cpu.abilist 2>/dev/null | grep -o 64)" ] && echo 'true' || echo 'false')"
    
    log_success "测试环境初始化完成"
}

# 测试模块结构
test_structure() {
    log_info "测试模块结构..."
    
    local errors=0
    local module_dir="$TEST_DIR/module"
    
    # 检查必需文件
    local required_files=("module.prop")
    for file in "${required_files[@]}"; do
        if [ ! -f "$module_dir/$file" ]; then
            log_error "缺少必需文件: $file"
            ((errors++))
        else
            log_success "找到必需文件: $file"
        fi
    done
    
    # 检查推荐文件
    local recommended_files=("service.sh" "META-INF/com/google/android/update-binary")
    for file in "${recommended_files[@]}"; do
        if [ ! -f "$module_dir/$file" ]; then
            log_warning "缺少推荐文件: $file"
        else
            log_success "找到推荐文件: $file"
        fi
    done
    
    # 检查目录结构
    if [ -d "$module_dir/system" ]; then
        log_success "找到system目录"
    else
        log_warning "未找到system目录"
    fi
    
    if [ "$errors" -eq 0 ]; then
        log_success "模块结构测试通过"
        return 0
    else
        log_error "模块结构测试失败: $errors 个错误"
        return 1
    fi
}

# 测试脚本语法
test_syntax() {
    log_info "测试脚本语法..."
    
    local errors=0
    local module_dir="$TEST_DIR/module"
    
    # 测试shell脚本语法
    local scripts=("service.sh" "post-fs-data.sh" "boot-completed.sh" "uninstall.sh" "customize.sh")
    for script in "${scripts[@]}"; do
        if [ -f "$module_dir/$script" ]; then
            log_debug "检查脚本语法: $script"
            if bash -n "$module_dir/$script"; then
                log_success "脚本语法正确: $script"
            else
                log_error "脚本语法错误: $script"
                ((errors++))
            fi
        fi
    done
    
    # 测试module.prop格式
    if [ -f "$module_dir/module.prop" ]; then
        log_debug "检查module.prop格式"
        local prop_errors=0
        
        # 检查必需字段
        local required_props=("id" "name" "version" "versionCode" "author")
        for prop in "${required_props[@]}"; do
            if ! grep -q "^$prop=" "$module_dir/module.prop"; then
                log_error "module.prop缺少必需字段: $prop"
                ((prop_errors++))
            fi
        done
        
        # 检查ID格式
        local module_id=$(grep "^id=" "$module_dir/module.prop" | cut -d'=' -f2)
        if [[ ! "$module_id" =~ ^[a-zA-Z][a-zA-Z0-9._-]+$ ]]; then
            log_error "模块ID格式无效: $module_id"
            ((prop_errors++))
        fi
        
        if [ "$prop_errors" -eq 0 ]; then
            log_success "module.prop格式正确"
        else
            ((errors+=prop_errors))
        fi
    fi
    
    if [ "$errors" -eq 0 ]; then
        log_success "语法测试通过"
        return 0
    else
        log_error "语法测试失败: $errors 个错误"
        return 1
    fi
}

# 测试权限设置
test_permissions() {
    log_info "测试权限设置..."
    
    local warnings=0
    local module_dir="$TEST_DIR/module"
    
    # 检查脚本执行权限
    local scripts=("service.sh" "post-fs-data.sh" "boot-completed.sh" "uninstall.sh")
    for script in "${scripts[@]}"; do
        if [ -f "$module_dir/$script" ]; then
            if [ -x "$module_dir/$script" ]; then
                log_success "脚本权限正确: $script"
            else
                log_warning "脚本缺少执行权限: $script"
                chmod +x "$module_dir/$script"
                log_info "已自动修复权限: $script"
                ((warnings++))
            fi
        fi
    done
    
    # 检查二进制文件权限
    if [ -d "$module_dir/system/bin" ]; then
        find "$module_dir/system/bin" -type f | while read -r binary; do
            if [ -x "$binary" ]; then
                log_success "二进制文件权限正确: $(basename "$binary")"
            else
                log_warning "二进制文件缺少执行权限: $(basename "$binary")"
                ((warnings++))
            fi
        done
    fi
    
    if [ "$warnings" -eq 0 ]; then
        log_success "权限测试通过"
        return 0
    else
        log_warning "权限测试完成，有 $warnings 个警告"
        return 1
    fi
}

# 模拟安装测试
test_install() {
    log_info "测试模块安装过程..."
    
    local module_dir="$TEST_DIR/module"
    local install_dir="$TEST_DIR/install"
    
    mkdir -p "$install_dir"
    
    # 模拟安装环境
    export MODPATH="$install_dir"
    export TMPDIR="$TEST_DIR/tmp"
    export ZIPFILE="$TEST_DIR/module.zip"
    mkdir -p "$TMPDIR"
    
    # 创建模拟的安装函数
    ui_print() {
        echo "[UI] $1"
    }
    
    abort() {
        log_error "安装中止: $1"
        return 1
    }
    
    set_perm() {
        local target="$1"
        local owner="$2"
        local group="$3"
        local perm="$4"
        local context="${5:-u:object_r:system_file:s0}"
        log_debug "设置权限: $target ($owner:$group $perm $context)"
    }
    
    set_perm_recursive() {
        local target="$1"
        local owner="$2"
        local group="$3"
        local dperm="$4"
        local fperm="$5"
        local context="${6:-u:object_r:system_file:s0}"
        log_debug "递归设置权限: $target ($owner:$group $dperm/$fperm $context)"
    }
    
    export -f ui_print abort set_perm set_perm_recursive
    
    # 执行安装脚本
    if [ -f "$module_dir/customize.sh" ]; then
        log_info "执行customize.sh..."
        cd "$module_dir"
        if bash customize.sh; then
            log_success "customize.sh执行成功"
        else
            log_error "customize.sh执行失败"
            return 1
        fi
    else
        log_info "未找到customize.sh，跳过自定义安装"
    fi
    
    log_success "安装测试完成"
    return 0
}

# 测试脚本执行
test_scripts() {
    log_info "测试模块脚本执行..."
    
    local module_dir="$TEST_DIR/module"
    local errors=0
    
    # 创建模拟环境
    export MODDIR="$module_dir"
    
    # 测试各个脚本
    local scripts=("service.sh" "post-fs-data.sh" "boot-completed.sh")
    for script in "${scripts[@]}"; do
        if [ -f "$module_dir/$script" ]; then
            log_info "测试脚本: $script"
            
            # 在子shell中执行脚本以避免影响当前环境
            if (
                cd "$module_dir"
                timeout 10s bash "$script" 2>&1 | head -20
            ); then
                log_success "脚本执行成功: $script"
            else
                local exit_code=$?
                if [ "$exit_code" -eq 124 ]; then
                    log_warning "脚本执行超时: $script"
                else
                    log_error "脚本执行失败: $script (退出码: $exit_code)"
                    ((errors++))
                fi
            fi
        fi
    done
    
    if [ "$errors" -eq 0 ]; then
        log_success "脚本测试通过"
        return 0
    else
        log_error "脚本测试失败: $errors 个错误"
        return 1
    fi
}

# 测试WebUI功能
test_webui() {
    log_info "测试WebUI功能..."
    
    local module_dir="$TEST_DIR/module"
    
    if [ ! -d "$module_dir/webroot" ]; then
        log_info "未找到webroot目录，跳过WebUI测试"
        return 0
    fi
    
    # 检查WebUI文件
    if [ -f "$module_dir/webroot/index.html" ]; then
        log_success "找到WebUI主页"
        
        # 验证HTML语法（简单检查）
        if grep -q "<html" "$module_dir/webroot/index.html" && grep -q "</html>" "$module_dir/webroot/index.html"; then
            log_success "HTML文件格式正确"
        else
            log_warning "HTML文件格式可能有问题"
        fi
    else
        log_warning "webroot目录存在但缺少index.html"
        return 1
    fi
    
    # 检查其他Web资源
    local web_files=$(find "$module_dir/webroot" -name "*.css" -o -name "*.js" -o -name "*.png" -o -name "*.jpg" | wc -l)
    if [ "$web_files" -gt 0 ]; then
        log_success "找到 $web_files 个Web资源文件"
    fi
    
    log_success "WebUI测试完成"
    return 0
}

# 兼容性测试
test_compatibility() {
    log_info "测试模块兼容性..."
    
    local module_dir="$TEST_DIR/module"
    local warnings=0
    
    # 检查Magisk兼容性
    if grep -q "MAGISK" "$module_dir"/* 2>/dev/null; then
        log_success "发现Magisk兼容性代码"
    else
        log_info "未发现Magisk特定代码"
    fi
    
    # 检查KernelSU特定代码
    if grep -q "KSU" "$module_dir"/* 2>/dev/null; then
        log_success "发现KernelSU特定代码"
    else
        log_warning "未发现KernelSU特定代码"
        ((warnings++))
    fi
    
    # 检查Android版本兼容性
    if [ -f "$module_dir/module.prop" ]; then
        if grep -q "minApi\|maxApi" "$module_dir/module.prop"; then
            log_success "发现API版本限制"
        else
            log_info "未设置API版本限制"
        fi
    fi
    
    if [ "$warnings" -eq 0 ]; then
        log_success "兼容性测试通过"
        return 0
    else
        log_warning "兼容性测试完成，有 $warnings 个警告"
        return 1
    fi
}

# 安全性检查
test_security() {
    log_info "执行安全性检查..."
    
    local module_dir="$TEST_DIR/module"
    local issues=0
    
    # 检查危险命令
    local dangerous_patterns=("rm -rf /" "format" "dd if=" ">" "chmod 777")
    for pattern in "${dangerous_patterns[@]}"; do
        if grep -r "$pattern" "$module_dir" >/dev/null 2>&1; then
            log_warning "发现潜在危险命令: $pattern"
            ((issues++))
        fi
    done
    
    # 检查硬编码路径
    if grep -r "/data/data" "$module_dir" >/dev/null 2>&1; then
        log_warning "发现硬编码的应用数据路径"
        ((issues++))
    fi
    
    # 检查网络访问
    if grep -r "curl\|wget\|nc\|netcat" "$module_dir" >/dev/null 2>&1; then
        log_info "发现网络访问代码，请确保安全"
    fi
    
    if [ "$issues" -eq 0 ]; then
        log_success "安全性检查通过"
        return 0
    else
        log_warning "安全性检查完成，发现 $issues 个潜在问题"
        return 1
    fi
}

# 运行所有测试
run_all_tests() {
    log_info "运行所有测试..."
    
    local total_tests=0
    local passed_tests=0
    
    local tests=("structure" "syntax" "permissions" "install" "scripts" "webui" "compatibility" "security")
    
    for test_name in "${tests[@]}"; do
        ((total_tests++))
        echo
        log_info "开始测试: $test_name"
        if "test_$test_name"; then
            ((passed_tests++))
            log_success "测试通过: $test_name"
        else
            log_error "测试失败: $test_name"
        fi
    done
    
    echo
    log_info "测试总结: $passed_tests/$total_tests 通过"
    
    if [ "$passed_tests" -eq "$total_tests" ]; then
        log_success "所有测试通过！"
        return 0
    else
        log_error "有测试失败，请检查模块"
        return 1
    fi
}

# 主函数
main() {
    local module_dir=""
    local test_name=""
    local run_all=false
    
    # 解析参数
    while [[ $# -gt 0 ]]; do
        case $1 in
            -s|--simulate)
                SIMULATOR_MODE="true"
                shift
                ;;
            -d|--debug)
                export DEBUG=1
                shift
                ;;
            -c|--clean)
                cleanup
                log_success "测试环境已清理"
                exit 0
                ;;
            -l|--list-tests)
                echo "可用的测试项目:"
                echo "  structure      - 模块结构测试"
                echo "  syntax         - 脚本语法测试"
                echo "  permissions    - 权限设置测试"
                echo "  install        - 安装过程测试"
                echo "  scripts        - 脚本执行测试"
                echo "  webui          - WebUI功能测试"
                echo "  compatibility  - 兼容性测试"
                echo "  security       - 安全性检查"
                exit 0
                ;;
            -t|--test)
                test_name="$2"
                shift 2
                ;;
            -a|--all-tests)
                run_all=true
                shift
                ;;
            -o|--output)
                TEST_DIR="$2"
                shift 2
                ;;
            -v|--verbose)
                export DEBUG=1
                shift
                ;;
            -h|--help)
                show_help
                exit 0
                ;;
            -*)
                error_exit "未知选项: $1"
                ;;
            *)
                if [ -z "$module_dir" ]; then
                    module_dir="$1"
                else
                    error_exit "多余的参数: $1"
                fi
                shift
                ;;
        esac
    done
    
    # 检查必需参数
    if [ -z "$module_dir" ]; then
        error_exit "请指定模块目录"
    fi
    
    if [ ! -d "$module_dir" ]; then
        error_exit "模块目录不存在: $module_dir"
    fi
    
    # 设置陷阱处理
    trap cleanup EXIT
    
    # 初始化测试环境
    init_test_env "$module_dir"
    
    # 运行测试
    if [ "$run_all" = true ]; then
        run_all_tests
    elif [ -n "$test_name" ]; then
        if declare -f "test_$test_name" >/dev/null; then
            "test_$test_name"
        else
            error_exit "未知的测试项目: $test_name"
        fi
    else
        # 默认运行基本测试
        test_structure && test_syntax && test_permissions
    fi
}

# 运行主函数
main "$@"
