plugins {
    id("scala")
    id("org.scoverage") version "8.1"
    id("io.quarkus")
    id("jacoco")
}

@Suppress("UNCHECKED_CAST")
val versions = rootProject.extra["VERSIONS"] as Map<String, String>

repositories {
    mavenCentral()
    mavenLocal()
}

scala {
    scalaVersion = versions["SCALA3"]!!
}

scoverage {
    scoverageVersion.set(versions["SCOVERAGE"]!!)
}

tasks.withType<ScalaCompile> {
    scalaCompileOptions.additionalParameters = listOf("-encoding", "UTF-8")
}

val quarkusPlatformGroupId: String by project
val quarkusPlatformArtifactId: String by project
val quarkusPlatformVersion: String by project

dependencies {
    implementation(project(":modules:api"))
    implementation(project(":modules:core"))
    implementation(project(":modules:io"))
    implementation(project(":modules:rule"))
    implementation(project(":modules:ui"))

    implementation(enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}"))
    implementation("io.quarkus:quarkus-rest")
    implementation("io.quarkus:quarkus-rest-jackson")
    implementation("io.quarkus:quarkus-config-yaml")
    implementation("io.quarkus:quarkus-arc")
    implementation("io.quarkus:quarkus-smallrye-openapi")

    implementation("com.fasterxml.jackson.module:jackson-module-scala_3:${versions["JACKSON_SCALA"]!!}")

    testImplementation(platform("org.junit:junit-bom:${versions["JUNIT_BOM"]!!}"))
    testImplementation("org.junit.jupiter:junit-jupiter")
    testImplementation("org.scalatest:scalatest_3:${versions["SCALATEST"]!!}")
    testImplementation("co.helmethair:scalatest-junit-runner:${versions["SCALATEST_JUNIT"]!!}")
    testImplementation("io.quarkus:quarkus-junit5")
    testImplementation("io.quarkus:quarkus-jacoco")
    testImplementation("io.rest-assured:rest-assured")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

configurations.matching { !it.name.startsWith("scoverage") }.configureEach {
    resolutionStrategy.force("org.scala-lang:scala-library:${versions["SCALA_LIBRARY"]!!}")
}
configurations.scoverage {
    resolutionStrategy.eachDependency {
        if (requested.group == "org.scoverage" && requested.name.startsWith("scalac-scoverage-plugin_")) {
            useTarget("${requested.group}:scalac-scoverage-plugin_2.13.16:2.3.0")
        }
    }
}

group = "de.nowchess"
version = "1.0-SNAPSHOT"

tasks.withType<JavaCompile> {
    options.encoding = "UTF-8"
    options.compilerArgs.add("-parameters")
}

tasks.withType<Jar>().configureEach {
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}

tasks.test {
    useJUnitPlatform {
        includeEngines("scalatest", "junit-jupiter")
    }
    testLogging {
        events("passed", "skipped", "failed")
    }
    finalizedBy(tasks.named("jacocoTestReport"))
}

tasks.jacocoTestReport {
    dependsOn(tasks.test)
    executionData.setFrom(
        layout.buildDirectory.file("jacoco-quarkus.exec"),
        layout.buildDirectory.file("jacoco/test.exec"),
    )
    sourceDirectories.setFrom(files("src/main/scala"))
    classDirectories.setFrom(
        files(layout.buildDirectory.dir("classes/scala/main")).asFileTree.matching {
            exclude(
                // App entrypoint (intentionally excluded)
                "**/AppMain*.class", "**/AppMain\$*.class",
                // DTO companion objects — only framework synthetics (writeReplace, fromProduct, unapply)
                "**/dto/GameStateResponse\$.class",
                "**/dto/PlayerInfoDto\$.class",
                "**/dto/LegalMovesResponse\$.class",
                "**/dto/ImportFenRequest\$.class",
                "**/dto/CreateGameRequest\$.class",
                "**/dto/OkResponse\$.class",
                "**/dto/LegalMoveDto\$.class",
                "**/dto/GameFullResponse\$.class",
                "**/dto/ImportPgnRequest\$.class",
                "**/dto/ApiErrorResponse\$.class",
                // Private implementation detail — inaccessible from tests
                "**/game/ServiceState.class", "**/game/ServiceState\$.class",
                // GameResult: sealed trait companion + case object singletons (only synthetics)
                "**/game/GameResult\$.class",
                "**/game/GameResult\$AgreedDraw\$.class",
                "**/game/GameResult\$FiftyMoveDraw\$.class",
                // GameResult.Resign companion (writeReplace, fromProduct; instance class kept)
                "**/game/GameResult\$Resign\$.class",
                // Other companion objects with only framework synthetics
                "**/game/GameId\$.class",
                "**/game/GameSnapshot\$.class",
            )
        }
    )
    reports {
        xml.required.set(true)
        xml.outputLocation.set(
            layout.buildDirectory.file("reports/jacoco/test/jacocoTestReport.xml")
        )
        html.required.set(false)
    }
}