// 配置
def outputDir = project.file("cpp/header")
def configFile = project.file("config/jni-classes.txt")

// 日志函数
def log(msg) {
    println "[JNI] $msg"
}

def logError(msg) {
    println "[JNI ERROR] $msg"
}

def logWarn(msg) {
    println "[JNI WARN] $msg"
}

// 创建配置任务
tasks.register('createJniConfig') {
    group = 'jni'
    description = '创建 JNI 配置文件模板'

    doLast {
        configFile.parentFile.mkdirs()
        if (!configFile.exists()) {
            configFile.text = """# JNI 头文件生成配置
# 每行一个类全限定名，例如：
# com.example.MyNativeClass
# com.example.NativeUtils

# 或者使用正则表达式自动匹配：
# #auto:.*Native.*
"""
            log "配置文件已创建: ${configFile.absolutePath}"
            log "请编辑此文件并添加包含 native 方法的类"
        }
    }
}

// 生成头文件任务
tasks.register('generateJniHeaders') {
    group = 'jni'
    description = '生成 JNI 头文件'

    dependsOn 'compileJava'

    doLast {
        // 确保目录存在
        outputDir.mkdirs()

        // 读取配置
        def targetClasses = []
        if (configFile.exists()) {
            configFile.eachLine { line ->
                def trimmed = line.trim()
                if (trimmed && !trimmed.startsWith('#')) {
                    targetClasses.add(trimmed)
                }
            }
        }

        if (targetClasses.isEmpty()) {
            logError "没有配置任何 JNI 类"
            logError "请先运行: ./gradlew createJniConfig"
            logError "然后编辑 ${configFile.absolutePath} 添加类名"
            return
        }

        log "开始生成 JNI 头文件..."
        log "目标类 (${targetClasses.size()} 个):"
        targetClasses.eachWithIndex { className, i ->
            log "  ${i + 1}. $className"
        }

        // 准备类路径
        def classesDir = project.sourceSets.main.output.classesDirs.singleFile
        def classpath = project.configurations.runtimeClasspath.asPath +
                File.pathSeparator +
                classesDir.absolutePath

        // 查找对应的 Java 源文件
        def sourceFiles = []
        def sourceDirs = project.sourceSets.main.java.srcDirs

        targetClasses.each { className ->
            def found = false
            def relativePath = className.replace('.', '/') + '.java'

            sourceDirs.each { srcDir ->
                def sourceFile = new File(srcDir, relativePath)
                if (sourceFile.exists()) {
                    sourceFiles.add(sourceFile)
                    found = true
                    log "找到源文件: ${sourceFile.absolutePath}"
                }
            }

            if (!found) {
                logWarn "警告: 未找到类 $className 的源文件"
            }
        }

        if (sourceFiles.isEmpty()) {
            logError "错误: 未找到任何源文件"
            logError "请确保源文件存在于 src/main/java/ 目录中"
            return
        }

        // 使用 javac -h 命令（正确的方式）
        def javaHome = System.getProperty('java.home')
        def javacPath = "${javaHome}/bin/javac"

        if (!new File(javacPath).exists()) {
            javacPath = "${javaHome}/bin/javac"
        }

        log "使用 javac -h 生成头文件..."

        // 构建临时目录用于编译输出
        def tempOutputDir = new File(project.buildDir, "tmp/jni-headers")
        tempOutputDir.mkdirs()

        try {
            // 方式1：逐个类生成（更可靠）
            def successCount = 0
            def failCount = 0

            sourceFiles.each { sourceFile ->
                try {
                    // 构建 javac 命令
                    def processArgs = [
                            javacPath,
                            '-h', outputDir.absolutePath,  // 头文件输出目录
                            '-cp', classpath,              // 类路径
                            '-d', tempOutputDir.absolutePath,  // 类文件输出目录
                            sourceFile.absolutePath        // 源文件
                    ]

                    log "处理: ${sourceFile.name}"

                    def process = processArgs.execute()
                    def stdout = new StringBuilder()
                    def stderr = new StringBuilder()

                    process.consumeProcessOutput(stdout, stderr)
                    def exitCode = process.waitFor()

                    if (exitCode == 0) {
                        successCount++
                        if (stdout.length() > 0) {
                            log "  输出: ${stdout.toString().trim()}"
                        }
                    } else {
                        failCount++
                        logError "  处理失败: ${sourceFile.name}"
                        if (stderr.length() > 0) {
                            logError "  错误: ${stderr.toString().trim()}"
                        }
                    }

                } catch (Exception e) {
                    failCount++
                    logError "  处理异常: ${e.message}"
                }
            }

            log "处理完成: 成功 ${successCount} 个, 失败 ${failCount} 个"

            if (successCount > 0) {
                // 检查生成了哪些头文件
                def headerFiles = outputDir.listFiles({ dir, name -> name.endsWith('.h') } as FilenameFilter)
                if (headerFiles && headerFiles.size() > 0) {
                    log "=" * 60
                    log "JNI 头文件生成成功！"
                    log "=" * 60
                    log "输出目录: ${outputDir.absolutePath}"
                    log "生成的头文件 (${headerFiles.size()} 个):"

                    headerFiles.sort { it.name }.each { file ->
                        def size = file.length()
                        def sizeStr = size < 1024 ? "${size} B" : "${String.format("%.1f", size / 1024.0)} KB"
                        log "  ✓ ${file.name} ($sizeStr)"

                        // 显示文件开头几行
                        try {
                            def lines = file.readLines()
                            if (lines.size() > 0) {
                                def headerGuard = lines.find { it.contains('#ifndef') }
                                if (headerGuard) {
                                    log "    头文件保护: ${headerGuard.trim()}"
                                }
                            }
                        } catch (Exception e) {
                            // 忽略读取错误
                        }
                    }

                    log "=" * 60
                    log "🎉 头文件已成功生成！"
                    log ""
                    log "使用建议:"
                    log "  1. 将生成的头文件复制到你的 C/C++ 项目中"
                    log "  2. 在 C/C++ 源文件中包含这些头文件"
                    log "  3. 实现头文件中声明的 JNI 函数"
                    log ""
                    log "示例 C++ 代码:"
                    log "  #include \"${headerFiles[0].name}\""
                    log "  JNIEXPORT void JNICALL Java_com_example_MyClass_nativeMethod(JNIEnv* env, jobject obj) {"
                    log "      // 你的实现代码"
                    log "  }"

                } else {
                    logWarn "警告: 未生成任何 .h 头文件"
                    logWarn "可能的原因:"
                    logWarn "  1. 源文件中没有 native 方法声明"
                    logWarn "  2. javac 版本不支持 -h 选项"
                    logWarn "  3. 类路径配置不正确"
                }
            } else {
                logError "所有处理都失败，未生成任何头文件"
            }

        } finally {
            // 清理临时目录
            tempOutputDir.deleteDir()
        }
    }
}

// 备选方案：使用传统 javah（如果 javac -h 失败）
tasks.register('generateJniHeadersLegacy') {
    group = 'jni'
    description = '使用传统 javah 生成 JNI 头文件'

    dependsOn 'compileJava'

    doLast {
        outputDir.mkdirs()

        def targetClasses = []
        if (configFile.exists()) {
            configFile.eachLine { line ->
                def trimmed = line.trim()
                if (trimmed && !trimmed.startsWith('#')) {
                    targetClasses.add(trimmed)
                }
            }
        }

        if (targetClasses.isEmpty()) {
            logError "没有配置任何 JNI 类"
            return
        }

        log "使用传统 javah 生成头文件..."

        def classesDir = project.sourceSets.main.output.classesDirs.singleFile
        def classpath = project.configurations.runtimeClasspath.asPath +
                File.pathSeparator +
                classesDir.absolutePath

        def javaHome = System.getProperty('java.home')
        def javahPath = "${javaHome}/bin/javah"

        if (!new File(javahPath).exists()) {
            javahPath = "${javaHome}/../bin/javah"
        }

        if (!new File(javahPath).exists()) {
            logError "找不到 javah 工具"
            logError "请使用 Java 8-9 或使用 generateJniHeaders 任务"
            return
        }

        def processArgs = [javahPath, '-classpath', classpath, '-d', outputDir.absolutePath]
        processArgs.addAll(targetClasses)

        log "执行命令: ${processArgs.join(' ')}"

        def process = processArgs.execute()
        def exitCode = process.waitFor()

        if (exitCode == 0) {
            def files = outputDir.listFiles({ dir, name -> name.endsWith('.h') } as FilenameFilter)
            log "生成成功！创建了 ${files?.size() ?: 0} 个头文件"
            if (files) {
                files.each { log "  - ${it.name}" }
            }
        } else {
            logError "生成失败"
        }
    }
}

// 扫描 native 方法任务
tasks.register('scanForNativeMethods') {
    group = 'jni'
    description = '扫描项目中的 native 方法'

    doLast {
        log "扫描项目中可能包含 native 方法的类..."

        def sourceDirs = project.sourceSets.main.java.srcDirs
        def foundClasses = []

        sourceDirs.each { srcDir ->
            if (srcDir.exists()) {
                srcDir.eachFileRecurse(groovy.io.FileType.FILES) { file ->
                    if (file.name.endsWith('.java')) {
                        def content = file.text
                        if (content.contains('native ') || content.contains(' native')) {
                            // 提取类名
                            def packageMatch = content =~ /package\s+([\w.]+)\s*;/
                            def classMatch = content =~ /class\s+(\w+)/

                            if (packageMatch.find() && classMatch.find()) {
                                def packageName = packageMatch.group(1)
                                def className = classMatch.group(1)
                                def fullClassName = "${packageName}.${className}"

                                if (!foundClasses.contains(fullClassName)) {
                                    foundClasses.add(fullClassName)
                                    log "发现: $fullClassName"
                                }
                            }
                        }
                    }
                }
            }
        }

        if (foundClasses.isEmpty()) {
            log "未发现包含 native 方法的类"
        } else {
            log "=" * 60
            log "发现 ${foundClasses.size()} 个可能包含 native 方法的类:"
            foundClasses.sort().eachWithIndex { cls, i ->
                log "  ${i + 1}. $cls"
            }
            log ""
            log "你可以将这些类添加到 ${configFile.name} 中"
        }
    }
}

// 清理任务
tasks.register('cleanJniHeaders', Delete) {
    group = 'jni'
    description = '清理 JNI 头文件'
    delete outputDir

    doLast {
        log "已清理 JNI 头文件目录: ${outputDir.absolutePath}"
    }
}

// 验证任务
tasks.register('verifyJniSetup') {
    group = 'jni'
    description = '验证 JNI 配置'

    doLast {
        log "验证 JNI 配置..."
        log "Java 版本: ${System.getProperty('java.version')}"
        log "Java Home: ${System.getProperty('java.home')}"

        // 检查 javac
        def javaHome = System.getProperty('java.home')
        def javacPath = "${javaHome}/bin/javac"
        def javacExists = new File(javacPath).exists() || new File("${javaHome}/../bin/javac").exists()
        log "javac 工具: ${javacExists ? '找到 ✓' : '未找到 ✗'}"

        // 检查 javah（传统方式）
        def javahPath = "${javaHome}/bin/javah"
        def javahExists = new File(javahPath).exists() || new File("${javaHome}/../bin/javah").exists()
        log "javah 工具: ${javahExists ? '找到 ✓' : '未找到 ✗'}"

        // 检查配置文件
        if (configFile.exists()) {
            def classes = configFile.readLines()
                    .findAll { it.trim() && !it.trim().startsWith('#') }
            log "配置文件: 已找到 (${classes.size()} 个类)"
            if (classes.size() > 0) {
                classes.each { log "  - $it" }
            }
        } else {
            log "配置文件: 未找到 ✗"
        }

        // 检查输出目录
        log "输出目录: ${outputDir.absolutePath}"
    }
}

// 帮助任务
tasks.register('jniHelp') {
    group = 'help'
    description = 'JNI 帮助'

    doLast {
        println """
${'=' * 70}
JNI 头文件生成系统
${'=' * 70}

📋 概述:
   为包含 native 方法的 Java 类生成 C/C++ 头文件。

🚀 快速开始:
   1. ./gradlew createJniConfig          # 创建配置文件
   2. 编辑 config/jni-classes.txt        # 添加你的 JNI 类
   3. ./gradlew generateJniHeaders       # 生成头文件（推荐）
   4. 头文件输出到: cpp/header/

🔧 可用任务:
   jniHelp                  - 显示此帮助
   createJniConfig          - 创建配置文件
   generateJniHeaders       - 生成头文件（现代方式）
   generateJniHeadersLegacy - 传统方式（Java 8-9）
   scanForNativeMethods     - 扫描 native 方法
   verifyJniSetup           - 验证配置
   cleanJniHeaders          - 清理生成的文件

📝 配置文件格式 (config/jni-classes.txt):
   # 注释
   com.example.MyNativeClass     # 直接指定类名
   #auto:.*Native.*              # 自动匹配（以 #auto: 开头）

⚠️  注意事项:
   • 确保类中包含 native 方法声明
   • 先编译项目再生成头文件
   • 对于 Java 10+ 使用 generateJniHeaders
   • 对于 Java 8-9 使用 generateJniHeadersLegacy

🔍 调试:
   • 运行 verifyJniSetup 检查环境
   • 运行 scanForNativeMethods 发现 native 类
   • 确保源文件中有 native 关键字

${'=' * 70}
"""
    }
}

// 可选：自动集成到构建
// tasks.named('build') {
//     dependsOn tasks.named('generateJniHeaders')
// }

// 清理时包含 JNI 头文件
tasks.named('clean') {
    dependsOn tasks.named('cleanJniHeaders')
}

log "JNI 模块已加载"
log "输出目录: ${outputDir.absolutePath}"
log "配置文件: ${configFile.absolutePath}"
log "使用 ./gradlew jniHelp 查看详细帮助"