plugins {
    alias(libs.plugins.androidLibrary)
    id 'maven-publish'
    id 'jacoco'
}

// Force Jacoco to compatible version for Gradle 8.x + JDK 17
jacoco {
    toolVersion = "0.8.7"
}

group = 'com.github.anggastudio'
version = '1.0.1-SNAPSHOT'

android {
    namespace 'com.anggastudio.printama'
    compileSdk 36

    defaultConfig {
        minSdk 24

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles "consumer-rules.pro"
    }

    buildTypes {
        debug {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            consumerProguardFiles 'consumer-rules.pro'
            debuggable true
        }
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            consumerProguardFiles 'consumer-rules.pro'
        }
    }
    buildFeatures {
        buildConfig = true
    }
    java {
        toolchain {
            languageVersion = JavaLanguageVersion.of(17)
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }

    publishing {
        // Publishes "release" build component created by
        // Android Gradle plugin
        singleVariant("release") {
            withSourcesJar()
        }
    }

    testOptions {
        unitTests {
            // Required for Robolectric + resources
            includeAndroidResources = true
            all {
                jacoco {
                    includeNoLocationClasses = true
                    excludes = ['jdk.internal.*']  // Exclude JDK internal classes from instrumentation
                }
                // IMPORTANT: Open JDK modules for reflection/instrumentation on JDK 17+
                jvmArgs(
                        '--add-opens', 'java.base/java.lang=ALL-UNNAMED',
                        '--add-opens', 'java.base/java.lang.reflect=ALL-UNNAMED',
                        '--add-opens', 'java.base/java.io=ALL-UNNAMED',
                        '--add-opens', 'java.base/jdk.internal.reflect=ALL-UNNAMED',
                        '--add-exports', 'java.base/jdk.internal.reflect=ALL-UNNAMED'
                )

                // Force Gradle test workers to run on Java 17
                javaLauncher = project.javaToolchains.launcherFor {
                    languageVersion = JavaLanguageVersion.of(17)
                }

                maxParallelForks = 1
            }
        }
    }
}

afterEvaluate {
    publishing {
        publications {
            release(MavenPublication) {
                from components.release
                artifactId = 'Printama'
                pom {
                    name = 'Printama'
                    description = 'Android library for Bluetooth thermal printing'
                }
            }
        }
        repositories {
            mavenLocal()
        }
    }
}

dependencies {
    implementation libs.appcompat
    implementation libs.material

    // Unit Testing Dependencies
    testImplementation libs.junit
    testImplementation libs.mockito.core
    testImplementation libs.mockito.inline
    testImplementation libs.robolectric
    testImplementation libs.powermock.module.junit4
    testImplementation libs.powermock.api.mockito2
    testImplementation libs.core
    testImplementation libs.ext.junit

    // Android Testing Dependencies
    androidTestImplementation libs.ext.junit
    androidTestImplementation libs.espresso.core
    androidTestImplementation libs.runner
    androidTestImplementation libs.rules
    androidTestImplementation libs.fragment.testing
    androidTestImplementation libs.mockito.android
}

// Ensure all Test tasks inherit strict single-fork, JDK 17, and module opens
tasks.withType(Test).configureEach {
    maxParallelForks = 1
    forkEvery = 0
    jvmArgs(
            '--add-opens', 'java.base/java.lang=ALL-UNNAMED',
            '--add-opens', 'java.base/java.lang.reflect=ALL-UNNAMED',
            '--add-opens', 'java.base/java.io=ALL-UNNAMED',
            '--add-opens', 'java.base/java.util=ALL-UNNAMED',
            '--add-opens', 'java.base/java.util.concurrent=ALL-UNNAMED',
            '--add-opens', 'java.base/jdk.internal.reflect=ALL-UNNAMED',
            '--add-exports', 'java.base/jdk.internal.reflect=ALL-UNNAMED'
    )
    javaLauncher = project.javaToolchains.launcherFor {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

// Generate HTML + XML coverage report for unit tests
// tasks.register('jacocoTestReport', JacocoReport)
tasks.register('jacocoTestReport', JacocoReport) {
    dependsOn 'testDebugUnitTest'

    reports {
        html.required = true
        xml.required = true
    }

    def fileFilter = [
            '**/R.class', '**/R$*.class',
            '**/BuildConfig.*', '**/Manifest*.*',
            '**/*$*' // synthetic/anonymous classes
    ]

    // Use provider-based paths instead of $buildDir
    def javaClasses = layout.buildDirectory.dir("intermediates/javac/debug/classes")
    def kotlinClasses = layout.buildDirectory.dir("tmp/kotlin-classes/debug")

    classDirectories.from = files(
            javaClasses.map { it.asFileTree.matching { exclude fileFilter } },
            kotlinClasses.map { it.asFileTree.matching { exclude fileFilter } }
    )
    sourceDirectories.from = files('src/main/java')

    executionData.from = layout.buildDirectory.asFileTree.matching {
        include "jacoco/testDebugUnitTest.exec"
        include "outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec"
        include "**/*.exec"
        include "**/*.ec"
    }
}

// Enforce minimum coverage for unit tests
// tasks.register('jacocoTestCoverageVerification', JacocoCoverageVerification)
tasks.register('jacocoTestCoverageVerification', JacocoCoverageVerification) {
    dependsOn 'testDebugUnitTest'

    def fileFilter = [
            '**/R.class', '**/R$*.class',
            '**/BuildConfig.*', '**/Manifest*.*',
            '**/*$*'
    ]

    // Use provider-based paths instead of $buildDir
    def javaClasses = layout.buildDirectory.dir("intermediates/javac/debug/classes")
    def kotlinClasses = layout.buildDirectory.dir("tmp/kotlin-classes/debug")

    classDirectories.from = files(
            javaClasses.map { it.asFileTree.matching { exclude fileFilter } },
            kotlinClasses.map { it.asFileTree.matching { exclude fileFilter } }
    )
    sourceDirectories.from = files('src/main/java')

    executionData.from = layout.buildDirectory.asFileTree.matching {
        include "jacoco/testDebugUnitTest.exec"
        include "outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec"
        include "**/*.exec"
        include "**/*.ec"
    }

    violationRules {
        rule {
            limit {
                counter = 'INSTRUCTION'
                value = 'COVEREDRATIO'
                minimum = 0.60
            }
        }
    }
}

// Make 'check' fail if coverage is below threshold
tasks.named('check') {
    dependsOn 'jacocoTestCoverageVerification'
}

tasks.withType(JavaCompile).configureEach {
    options.compilerArgs += ['-parameters']
}
