import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.variant.FilterConfiguration

plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.kotlinxSerialization)
    alias(libs.plugins.ksp)
    alias(libs.plugins.compose.compiler)
    alias(libs.plugins.grgit)
    alias(libs.plugins.licensee)
}

ksp {
    arg("room.schemaLocation", "$projectDir/schemas")
}

licensee {
    allowedLicenses().forEach { allow(it) }
    allowedLicenseUrls().forEach { allowUrl(it) }
    // foss, but missing licenses
    ignoreDependencies("com.github.T8RIN.QuickieExtended")
    ignoreDependencies("com.github.topjohnwu.libsu")
}

configure<ApplicationExtension> {
    namespace = Constants.APP_ID
    compileSdk = Constants.TARGET_SDK

    androidResources { generateLocaleConfig = true }

    dependenciesInfo {
        includeInApk = false
        includeInBundle = false
    }

    // fix okhttp proguard issue
    packaging { resources { pickFirsts.add("okhttp3/internal/publicsuffix/publicsuffixes.gz") } }

    splits {
        abi {
            val noSplits = providers.gradleProperty("noSplits").isPresent
            isEnable = !noSplits
            reset()
            include("armeabi-v7a", "arm64-v8a")
            isUniversalApk = !noSplits
        }
    }

    defaultConfig {
        applicationId = Constants.APP_ID
        minSdk = Constants.MIN_SDK
        targetSdk = Constants.TARGET_SDK
        versionCode = Constants.VERSION_CODE
        versionName = Constants.VERSION_NAME

        experimentalProperties["android.experimental.disableGitVersion"] = true

        sourceSets {
            getByName("debug").assets.directories += "$projectDir/schemas"
        }

        val languagesProvider = project.languageListProvider()
        val languagesArray = buildLanguagesArray(languagesProvider.get())
        buildConfigField("String[]", "LANGUAGES", "new String[]{ $languagesArray }")

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables { useSupportLibrary = true }
    }

    signingConfigs {
        create(Constants.RELEASE) {
            storeFile = file(System.getenv("KEY_STORE_PATH") ?: "keystore/android_keystore.jks")
            storePassword =
                LocalProperties.get("SIGNING_STORE_PASSWORD")
                    ?: System.getenv("SIGNING_STORE_PASSWORD")
            keyAlias =
                LocalProperties.get("SIGNING_KEY_ALIAS") ?: System.getenv("SIGNING_KEY_ALIAS")
            keyPassword =
                LocalProperties.get("SIGNING_KEY_PASSWORD") ?: System.getenv("SIGNING_KEY_PASSWORD")
        }
    }

    buildTypes {
        packaging.jniLibs.keepDebugSymbols.addAll(
            listOf("libwg-go.so", "libwg-quick.so", "libwg.so")
        )

        release {
            isDebuggable = false
            isMinifyEnabled = true
            isShrinkResources = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro",
            )
            signingConfig = signingConfigs.getByName(Constants.RELEASE)
            resValue("string", "provider", "\"${Constants.APP_NAME}.provider\"")
        }

        debug {
            applicationIdSuffix = ".debug"
            resValue("string", "app_name", "WG Tunnel Debug")
            isDebuggable = true
            resValue("string", "provider", "\"${Constants.APP_NAME}.provider.debug\"")
        }

        create(Constants.NIGHTLY) {
            initWith(buildTypes.getByName(Constants.RELEASE))
            applicationIdSuffix = ".nightly"
            resValue("string", "app_name", "WG Tunnel Nightly")
            resValue("string", "provider", "\"${Constants.APP_NAME}.provider.nightly\"")
        }
    }

    flavorDimensions.add("type")
    productFlavors {
        create("fdroid") {
            dimension = "type"
            buildConfigField("String", "FLAVOR", "\"fdroid\"")
        }
        create("google") {
            dimension = "type"
            buildConfigField("String", "FLAVOR", "\"google\"")
        }
        create("standalone") {
            dimension = "type"
            buildConfigField("String", "FLAVOR", "\"standalone\"")
        }
    }

    compileOptions {
        isCoreLibraryDesugaringEnabled = true
    }

    buildFeatures {
        compose = true
        buildConfig = true
        resValues = true
    }
    packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" } }
}

androidComponents {
    onVariants { variant ->
        val isNightly = project.isNightlyBuild()

        if (isNightly) {
            variant.outputs.forEach { output ->

                output.versionCode.set(
                    output.versionCode.get() + project.getVersionCodeIncrement()
                )

                val currentVersion = output.versionName.get()
                val nextVersion = bumpToNextPatchVersion(currentVersion)
                val gitHash = project.getGitCommitHash()

                output.versionName.set("$nextVersion-nightly+git.$gitHash")
            }
        }

        val abiNameMap = mapOf(
            "armeabi-v7a" to "armv7",
            "arm64-v8a" to "arm64",
            "x86" to "x86",
            "x86_64" to "x64",
        )

        variant.outputs.forEach { output ->
            val abi = output.filters.find { it.filterType == FilterConfiguration.FilterType.ABI }?.identifier
            val flavorName = variant.productFlavors.joinToString("-") { it.second }
            val versionName = output.versionName.get()
            val baseFileName = "${Constants.APP_NAME}-${flavorName}-v${versionName}"

            val outputFileName = if (!abi.isNullOrEmpty()) {
                val shortAbiName = abiNameMap.getOrDefault(abi, abi)
                "${baseFileName}-${shortAbiName}.apk"
            } else {
                "${baseFileName}.apk"
            }

            output.outputFileName.set(outputFileName)
        }
    }
}

dependencies {
    implementation(project(":logcatter"))
    implementation(project(":networkmonitor"))
    implementation(project(":tunnel"))

    // Core foundations
    implementation(libs.bundles.androidx.core.full)
    implementation(libs.bundles.androidx.lifecycle.core)
    implementation(libs.bundles.androidx.appcompat)
    implementation(libs.bundles.androidx.storage)

    // Compose setup
    implementation(platform(libs.androidx.compose.bom))
    implementation(libs.bundles.androidx.compose.ui)
    implementation(libs.bundles.androidx.compose.material)
    implementation(libs.androidx.activity.compose)

    // Navigation
    implementation(libs.bundles.androidx.navigation3)
    implementation(libs.bundles.navigation.lifecycle)

    // Material and icons
    implementation(libs.bundles.google.material)
    implementation(libs.bundles.material.icons)

    // Database
    implementation(libs.bundles.androidx.room)
    implementation(libs.bundles.androidx.datastore)
    ksp(libs.androidx.room.compiler)

    implementation(libs.bundles.androidx.work)

    // Networking and serialization
    implementation(libs.bundles.ktor.client)
    implementation(libs.bundles.kotlinx.serialization)
    implementation(libs.ipaddress)

    // State management
    implementation(libs.bundles.orbit.mvi)

    // Shizuku
    implementation(libs.bundles.shizuku)

    // UI utilities
    implementation(libs.bundles.ui.utilities)
    implementation(libs.lottie.compose)
    implementation(libs.sonner)

    // Misc utilities
    implementation(libs.bundles.misc.utilities)
    coreLibraryDesugaring(libs.desugar.jdk.libs)

    // Accompanist
    implementation(libs.bundles.accompanist)

    // Lifecycle Compose
    implementation(libs.lifecycle.runtime.compose)

    // Testing
    testImplementation(libs.junit)
    testImplementation(libs.androidx.junit)
    androidTestImplementation(libs.androidx.junit)
    androidTestImplementation(libs.androidx.espresso.core)
    androidTestImplementation(platform(libs.androidx.compose.bom))
    androidTestImplementation(libs.androidx.compose.ui.test)
    androidTestImplementation(libs.androidx.room.testing)
    debugImplementation(libs.androidx.compose.ui.tooling)
    debugImplementation(libs.androidx.compose.manifest)

    debugImplementation(libs.leakcanary.android)

    // Room database backup
    implementation(libs.roomdatabasebackup) {
        exclude(group = "org.reactivestreams", module = "reactive-streams")
    }

    // DI
    implementation(platform(libs.koin.bom))
    implementation(libs.koin.core)
    implementation(libs.koin.android)
    implementation(libs.koin.compose.viewmodel)
    implementation(libs.koin.androidx.compose)
    implementation(libs.koin.androidx.navigation)
    implementation(libs.koin.lazy)
    implementation(libs.koin.worker)
}

tasks.register<Copy>("copyLicenseeJsonToAssets") {
    dependsOn("licensee")
    val outputAssets = layout.projectDirectory.dir("src/main/assets")
    from(layout.buildDirectory.file("reports/licensee/androidFdroidRelease/artifacts.json")) {
        rename("artifacts.json", "licenses.json")
    }
    into(outputAssets)
}

tasks.named("preBuild") { dependsOn("copyLicenseeJsonToAssets") }

// https://gist.github.com/obfusk/61046e09cee352ae6dd109911534b12e#fix-proposed-by-linsui-disable-baseline-profiles
tasks.configureEach {
    if (name.contains("ArtProfile")) {
        enabled = false
    }
}
