plugins {
    id "com.android.application"
    id "kotlin-android"
    // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
    id "dev.flutter.flutter-gradle-plugin"
}

// Release signing material is NEVER committed (see android/.gitignore). It is
// supplied at build time via either:
//   * environment variables — used by CI, which decodes a keystore from the
//     LINTHRA_KEYSTORE_BASE64 secret and sets LINTHRA_KEYSTORE_PATH, or
//   * a git-ignored android/key.properties file — for local release builds.
// Environment variables take precedence over key.properties. If no complete
// signing config is found, the release build is left UNSIGNED — F-Droid
// expects an unsigned release APK so it can sign the artifact with its own
// key. A build that is not release-signed must not be distributed as a real
// release. See docs/release-signing.md.
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file("key.properties")
if (keystorePropertiesFile.exists()) {
    keystorePropertiesFile.withInputStream { keystoreProperties.load(it) }
}

def resolveSigningValue = { String envKey, String propKey ->
    def value = System.getenv(envKey)
    if (value == null || value.isEmpty()) {
        value = keystoreProperties.getProperty(propKey)
    }
    return value
}

def releaseStoreFilePath = resolveSigningValue("LINTHRA_KEYSTORE_PATH", "storeFile")
def releaseStorePassword = resolveSigningValue("LINTHRA_KEYSTORE_PASSWORD", "storePassword")
def releaseKeyAlias = resolveSigningValue("LINTHRA_KEY_ALIAS", "keyAlias")
def releaseKeyPassword = resolveSigningValue("LINTHRA_KEY_PASSWORD", "keyPassword")

def hasReleaseSigning = releaseStoreFilePath != null && !releaseStoreFilePath.isEmpty() &&
    file(releaseStoreFilePath).exists() && releaseStorePassword != null &&
    releaseKeyAlias != null && releaseKeyPassword != null

if (hasReleaseSigning) {
    logger.lifecycle("Linthra: release build will be signed with the configured release keystore.")
} else {
    logger.lifecycle("Linthra: no release signing config found; release build will be UNSIGNED (e.g. for F-Droid, which signs it itself).")
}

android {
    namespace = "io.github.thezupzup.linthra"
    compileSdk = flutter.compileSdkVersion
    ndkVersion = flutter.ndkVersion

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

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8
    }

    // F-Droid's `check apk` step rejects any APK that carries extra APK
    // Signing Block entries, and AGP 8.x defaults to embedding a compressed
    // Maven dependency list (block id 0x504b4453, "Dependency metadata") so
    // Play Console can flag vulnerable libraries. The matching
    // android.dependenciesInfo.* flags in android/gradle.properties are NOT a
    // documented AGP knob — AGP only reads this setting from the DSL block
    // below, so the properties alone left the metadata in v0.1.0-alpha.38.
    // This DSL block is the supported off-switch and strips the block from
    // both APK and AAB outputs. Disabling has no runtime effect; it only
    // suppresses metadata that Google would have read.
    dependenciesInfo {
        includeInApk = false
        includeInBundle = false
    }

    defaultConfig {
        // Stable application ID for F-Droid / GitHub Releases distribution.
        applicationId = "io.github.thezupzup.linthra"
        minSdk = flutter.minSdkVersion
        targetSdk = flutter.targetSdkVersion
        // From Flutter (pubspec.yaml's `version: <name>+<code>`), the single
        // source of truth for the release version, kept in lockstep with the
        // release tag (CI verifies the match before building). A plain
        // `flutter build` — here and on F-Droid — reads both from pubspec.yaml;
        // no build-time override. See docs/release-process.md §1.
        versionCode = flutter.versionCode
        versionName = flutter.versionName
    }

    signingConfigs {
        if (hasReleaseSigning) {
            release {
                storeFile = file(releaseStoreFilePath)
                storePassword = releaseStorePassword
                keyAlias = releaseKeyAlias
                keyPassword = releaseKeyPassword
            }
        }
    }

    buildTypes {
        release {
            // Use the real release signing config when complete signing material
            // is available (env vars or key.properties). Otherwise leave the
            // release build UNSIGNED: F-Droid expects an unsigned release APK so
            // it can sign the artifact with its own key. (A build that is not
            // release-signed must never be distributed as a real release.)
            if (hasReleaseSigning) {
                signingConfig = signingConfigs.release
            }
        }
    }
}

// Per-ABI versionCode scheme for F-Droid's split-APK flow (MR !39329).
//
// When `flutter build apk --release --split-per-abi` runs, AGP produces one
// APK per ABI and each output carries an "ABI" filter. F-Droid needs a
// strictly distinct, monotonically ordered `versionCode` per ABI so the store
// can track each variant independently (and avoid the "APK has different libs
// in different ABI" code-quality finding flagged on MR !39329). The override
// leaves the base versionCode from `pubspec.yaml` untouched (so a plain
// `flutter build apk --release` — what the GitHub release CI runs — still
// ships the universal APK at e.g. `100039`) and only fires for outputs that
// have an ABI filter, encoding the ABI rank as
//
//     versionCodeOverride = baseVersionCode * 10 + abiRank
//
// with armeabi-v7a=1, arm64-v8a=2, x86_64=3. The matching `VercodeOperation`
// and per-ABI `Builds` entries (versionCodes 1000391/1000392/1000393) live in
// metadata/io.github.thezupzup.linthra.yml.
//
// MUST run AFTER the Flutter Gradle plugin's per-ABI override. The Flutter
// plugin (packages/flutter_tools/gradle/.../flutter.groovy, the
// `addFlutterDeps` closure called from `applicationVariants.all { variant ->
// ... addFlutterDeps(variant) ... }` at the bottom of `addFlutterTasks`)
// itself sets
//
//     output.versionCodeOverride = abiVersionCode * 1000 + variant.versionCode
//
// (with abiVersionCode = 1/2/4 for armeabi-v7a/arm64-v8a/x86_64) whenever
// `-Psplit-per-abi=true` is set — which `flutter build --split-per-abi`
// passes. For base versionCode 100039 that yields
//
//     armeabi-v7a -> 101039   arm64-v8a -> 102039   x86_64 -> 104039
//
// which is what alpha.39's F-Droid build hit: `Unexpected versionCode in
// output; APK: '101039', Expected: '1000391'`.
//
// Registration / lifecycle ordering — why this is at script top-level and
// NOT inside an `afterEvaluate { }`:
//
//   * The Flutter plugin registers its own `applicationVariants.all { ... }`
//     callback eagerly from `apply()` (at the `id "dev.flutter..."` line at
//     the top of this script), i.e. during the script's configuration phase.
//   * AGP's `DomainObjectCollection.all { }` queues actions in registration
//     order and fires them per variant as each variant is realized. So a
//     second `.all { }` registered later in the same script is guaranteed
//     to run AFTER Flutter's action on every variant, which is exactly what
//     "last writer wins" needs for `output.versionCodeOverride`.
//   * `afterEvaluate { }` (what alpha.39 used) is too late: by the time the
//     afterEvaluate queue drains, AGP has already locked the variant output
//     DSL properties as part of finalizing the project — assigning
//     `output.versionCodeOverride` then throws "The value for this property
//     cannot be changed any further", which is the F-Droid build failure
//     after PR #134.
//   * Registering here — at script top-level, AFTER the `android { }` block
//     so `android.applicationVariants` is reachable, but BEFORE
//     `flutter { source = "../.." }` and BEFORE project evaluation finishes
//     — puts our callback in the same hook lane as Flutter's and after
//     Flutter's registration, but still inside the configuration phase, so
//     AGP has not yet finalized the output properties when our action runs.
def fdroidAbiCodes = ["armeabi-v7a": 1, "arm64-v8a": 2, "x86_64": 3]
android.applicationVariants.all { variant ->
    variant.outputs.all { output ->
        def abiName = output.filters.find { it.filterType == "ABI" }?.identifier
        def abiCode = fdroidAbiCodes[abiName]
        if (abiCode != null) {
            output.versionCodeOverride = variant.versionCode * 10 + abiCode
        }
    }
}

flutter {
    source = "../.."
}
