// Media3 Engine plugin — Android-only ExoPlayer + FFmpeg audio decoder bridge.
//
// 依赖：
//   - Maven Central: media3-exoplayer / media3-datasource / media3-decoder 1.10.1
//   - 本地 AAR    : media3-decoder-ffmpeg-1.10.1-arm64.aar
//                  由 fileTree 从主 app 的 android/app/libs/ 加载。AAR 由
//                  scripts/build_media3_ffmpeg.sh 自编译产出，CHECKSUMS.txt
//                  记录 SHA-256。
//
//   AAR 缺失时 preBuild 任务会 fail-fast 抛出带恢复指引的错误（详见 README）。

import java.security.MessageDigest

plugins {
    id("com.android.library")
    id("kotlin-android")
}

group = "com.smplayer.media3_engine"
version = "0.0.1"

android {
    namespace = "com.smplayer.media3_engine"
    compileSdk = 36

    defaultConfig {
        minSdk = 24
        ndk {
            // 与主 app 保持一致：仅 arm64-v8a。其它 ABI 在 FFmpeg AAR 中也不存在，
            // 即便 ABI filter 漏了也只是无声的浪费（不会 crash）。
            abiFilters += listOf("arm64-v8a")
        }
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_17
        targetCompatibility = JavaVersion.VERSION_17
    }

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_17.toString()
    }

    buildFeatures {
        buildConfig = false
    }
}

repositories {
    google()
    mavenCentral()
}

// 自编译 FFmpeg audio decoder extension（arm64-v8a only，LGPL 配置）。AAR 由
// scripts/build_media3_ffmpeg.sh 产出，放在 android/app/libs/。
// 这里只声明 compileOnly：AGP 8 起禁止 library module 直接 implementation 本地
// .aar（"Direct local .aar file dependencies are not supported when building an
// AAR"），实际把 AAR 打入最终 APK 的责任落到主 app/build.gradle.kts 的
// `implementation(fileTree("libs"))`。本 plugin 编译期只需要 FfmpegAudioRenderer
// 等符号的可见性。
val media3Version = "1.10.1"
val ffmpegAarDir = file("../../../android/app/libs")
val ffmpegAarName = "media3-decoder-ffmpeg-$media3Version-arm64.aar"

dependencies {
    implementation("androidx.media3:media3-exoplayer:$media3Version")
    implementation("androidx.media3:media3-datasource:$media3Version")
    implementation("androidx.media3:media3-decoder:$media3Version")
    implementation("androidx.media3:media3-ui:$media3Version")
    compileOnly(fileTree(mapOf("dir" to ffmpegAarDir, "include" to listOf(ffmpegAarName))))
}

// AAR 缺失 / 篡改 fail-fast：在 preBuild 之前校验文件存在性 + SHA-256 与
// `android/app/libs/CHECKSUMS.txt` 一致。CI/Clean checkout 友好。
val verifyMedia3FfmpegAar by tasks.registering {
    group = "verification"
    description = "Verify media3 FFmpeg decoder AAR exists and matches CHECKSUMS.txt."
    val checksumsFile = ffmpegAarDir.resolve("CHECKSUMS.txt")
    val aarFile = ffmpegAarDir.resolve(ffmpegAarName)
    inputs.file(aarFile).withPropertyName("aar").withPathSensitivity(org.gradle.api.tasks.PathSensitivity.NONE)
    inputs.file(checksumsFile).withPropertyName("checksums").withPathSensitivity(org.gradle.api.tasks.PathSensitivity.NONE)
    doLast {
        if (!aarFile.isFile) {
            throw GradleException(
                """
                |Media3 FFmpeg decoder AAR is missing:
                |  expected: ${aarFile.absolutePath}
                |
                |This AAR is self-built (LGPL config, arm64-v8a,
                |codecs: dca/ac3/eac3/truehd/opus/vorbis/flac).
                |To produce it, run from the repo root:
                |
                |  scripts/build_media3_ffmpeg.sh
                |
                |Prerequisites: NDK r26b, JDK 17, ~30-60min wall-clock. See
                |plugins/media3_engine/README.md for full instructions and Docker recipe.
                |
                |If you only build the desktop (Windows/macOS) target, this Android
                |module is not on the dependency path and you can ignore this error.
                """.trimMargin()
            )
        }
        if (!checksumsFile.isFile) {
            throw GradleException(
                "Media3 AAR checksum manifest is missing: ${checksumsFile.absolutePath}\n" +
                "Restore CHECKSUMS.txt from git or rerun scripts/build_media3_ffmpeg.sh."
            )
        }
        // CHECKSUMS.txt 行格式：`<sha256>  <filename>`，可有 # 开头注释 / 空行
        val expectedSha = checksumsFile.readLines()
            .map { it.trim() }
            .firstOrNull { it.isNotEmpty() && !it.startsWith("#") && it.endsWith(ffmpegAarName) }
            ?.substringBefore(' ')
            ?.trim()
            ?.lowercase()
        if (expectedSha.isNullOrBlank() || !expectedSha.matches(Regex("^[0-9a-f]{64}$"))) {
            throw GradleException(
                "Media3 AAR checksum entry missing or malformed for $ffmpegAarName in " +
                "${checksumsFile.absolutePath}. Expected a line: '<sha256>  $ffmpegAarName'."
            )
        }
        val md = MessageDigest.getInstance("SHA-256")
        aarFile.inputStream().use { input ->
            val buffer = ByteArray(8192)
            while (true) {
                val n = input.read(buffer)
                if (n <= 0) break
                md.update(buffer, 0, n)
            }
        }
        val actualSha = md.digest().joinToString("") { "%02x".format(it) }
        if (actualSha != expectedSha) {
            throw GradleException(
                """
                |Media3 FFmpeg decoder AAR checksum mismatch — refusing to build.
                |  file     : ${aarFile.absolutePath}
                |  expected : $expectedSha  (from CHECKSUMS.txt)
                |  actual   : $actualSha
                |
                |The AAR has been replaced/corrupted since CHECKSUMS.txt was written.
                |If you intentionally rebuilt it, scripts/build_media3_ffmpeg.sh will
                |refresh CHECKSUMS.txt automatically; otherwise restore the file from git.
                """.trimMargin()
            )
        }
        logger.lifecycle("[verifyMedia3FfmpegAar] OK — sha256 $actualSha")
    }
}

afterEvaluate {
    tasks.named("preBuild").configure {
        dependsOn(verifyMedia3FfmpegAar)
    }
}
