/*
 * *******************************************************************************
 *  Copyright (c) 2025 Contributors to the Eclipse Foundation
 *
 *  See the NOTICE file(s) distributed with this work for additional
 *  information regarding copyright ownership.
 *
 *  This program and the accompanying materials are made available under the
 *  terms of the Apache License, Version 2.0 which is available at
 *  https://www.apache.org/licenses/LICENSE-2.0.
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 *  License for the specific language governing permissions and limitations
 *  under the License.
 *
 *  SPDX-License-Identifier: Apache-2.0
 * ******************************************************************************
 */

buildscript {
    repositories {
        mavenLocal()
        mavenCentral()
    }
    dependencies {
        classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}"
    }
}

plugins {
    id "de.undercouch.download" version "5.6.0"
    id "org.sonarqube" version "5.1.0.4882"
    id "java-platform"
    id "jacoco"
}

allprojects {
    repositories {
        mavenCentral()
    }
}

sonar {
    properties {
        property "sonar.host.url", "https://sonarcloud.io"
        property "sonar.projectKey", "eclipse-tractusx_ssi-dim-wallet-stub"
        property "sonar.organization", "eclipse-tractusx"
        property "sonar.qualitygate.wait", "true"
        property "sonar.coverage.jacoco.xmlReportPaths", "${project.buildDir}/reports/jacoco/test/jacocoTestReport.xml"
        property "sonar.java.coveragePlugin", "jacoco"
        property "sonar.dynamicAnalysis", "reuseReports"
        property "sonar.hotspot.enabled", "false"
        property "sonar.java.source", "21"
        property "sonar.java.target", "21"
    }
}

javaPlatform {
    allowDependencies() // Needed to import external BOMs
}

dependencies {
    api platform("org.springframework.boot:spring-boot-dependencies:${springBootVersion}")
    constraints {
        api "org.projectlombok:lombok:${lombokVersion}"
        api "org.springdoc:springdoc-openapi-starter-webmvc-ui:${springDocOpenapiVersion}"
        api "org.springdoc:springdoc-openapi-starter-common:${springDocOpenapiVersion}"
        api "org.springframework.cloud:spring-cloud-starter-openfeign:${springCloudOpenfeign}"

        api "org.eclipse.edc:crypto-common-lib:${edcLibVersion}"
        api "org.apache.commons:commons-lang3:${commonsLang3Version}"
        api "org.apache.commons:commons-text:${commonsTextVersion}"
        api "org.keycloak:keycloak-admin-client:${keycloakClientVersion}"

        api "com.h2database:h2:${h2databaseVersion}"

        api "com.github.curious-odd-man:rgxgen:${rgxgenVersion}"
        api "org.apache.httpcomponents.client5:httpclient5:${httpclient5Version}"
    }
}

group = "${group}"
version = "${version}"

subprojects {
    apply {
        plugin 'java'
//        plugin 'io.spring.dependency-management'
        plugin 'project-report'
        plugin "jacoco"
    }

    java {
        sourceCompatibility = JavaVersion.VERSION_21
    }

    configurations {
        compileOnly {
            extendsFrom annotationProcessor
        }
    }

    repositories {
        mavenLocal()
        mavenCentral()
    }

    dependencies {
        // LOMBOK
        implementation(enforcedPlatform(project(":")))
        annotationProcessor enforcedPlatform(project(":"))
        compileOnly("org.projectlombok:lombok")
        annotationProcessor("org.projectlombok:lombok")
    }

    test {
        useJUnitPlatform()
        finalizedBy jacocoTestReport
        testLogging {
            events("passed", "skipped", "failed")
        }
    }

    jacoco {
        toolVersion = "${jacocoVersion}"
    }



    build {
        archivesBaseName = "wallet"
        version = "${version}"
    }

    task allDeps(type: DependencyReportTask) {}

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


tasks.register('dashDownload', Download) {
    description = 'Download the Dash License Tool standalone jar'
    group = 'License'
    src 'https://repo.eclipse.org/service/local/artifact/maven/redirect?r=dash-licenses&g=org.eclipse.dash&a=org.eclipse.dash.licenses&v=LATEST'
    dest layout.projectDirectory.file('dash.jar')
    // will not replace an existing file. If you know you need a new version
    // then manually delete the file yourself, or run `dashClean`
    overwrite false
}


tasks.register('dashClean') {
    description = "Clean all files used by the 'License' group"
    group = 'License'
    logger.lifecycle("Removing 'dash.jar'")
    file('dash.jar').delete()
    logger.lifecycle("Removing 'deps.txt'")
    file('deps.txt').delete()
}

tasks.register('dashDependencies') { dashDependencies ->
    description = "Output all project dependencies from all subprojects as a flat list and save to 'deps.txt'."
    group = 'License'
    dashDependencies.dependsOn('dashDownload')
    doLast {
        def deps = []
        allprojects.each { proj ->
            proj.configurations.findAll { it.canBeResolved && it.name != 'archives' && it.name != 'default' }.each { conf ->
                deps.addAll(conf.incoming.resolutionResult.allDependencies
                        .findAll { it instanceof ResolvedDependencyResult }
                        .findAll { dep -> 
                            // Filter out internal project dependencies (those starting with ':')
                            // and only include external dependencies
                            def id = dep.selected.id
                            return !id.toString().startsWith(':') && 
                                   !id.toString().startsWith('project :') &&
                                   id.toString().contains(':')  // External dependencies have group:name:version format
                        }
                        .collect { dep -> "${dep.selected}" }
                )
            }
        }
        def uniqueSorted = deps.unique().sort()
        uniqueSorted.each { logger.quiet("{}", it) }
        file("deps.txt").write(uniqueSorted.join('\n'))
    }
}

tasks.register('dashLicenseCheck', JavaExec) { dashLicenseCheck ->
    description = "Run the Dash License Tool and save the summary in the 'DEPENDENCIES' file"
    group = 'License'
    dashLicenseCheck.dependsOn('dashDownload')
    dashLicenseCheck.dependsOn('dashDependencies')
    doFirst {
        classpath = files('dash.jar')
        // docs: https://eclipse-tractusx.github.io/docs/release/trg-7/trg-7-04
        args('-project', 'automotive.tractusx', '-summary', 'DEPENDENCIES', 'deps.txt')
    }
    doLast {
        logger.lifecycle("Removing 'deps.txt' now.")
        file('deps.txt').delete()
    }
}


// Add task to combine all JaCoCo reports
tasks.register('jacocoRootReport', JacocoReport) {
    description = 'Generates an aggregate report from all subprojects'
    group = 'verification'

    // Depend on all test tasks
    dependsOn(subprojects.test)

    // Get all JaCoCo execution data
    executionData {
        files(subprojects.jacocoTestReport.executionData)
    }

    // Define source files
    sourceDirectories.from = files(subprojects.sourceSets.main.allSource.srcDirs).files

    // Define class files
    classDirectories.from = files(subprojects.sourceSets.main.output).files

    reports {
        html {
            required = true
            outputLocation.set(file("${buildDir}/reports/jacoco/test/html"))
        }
        xml {
            required = true
            outputLocation.set(file("${buildDir}/reports/jacoco/test/jacocoTestReport.xml"))
        }
        csv.required = false
    }
}

// Add coverage verification task
tasks.register('jacocoCoverageVerification', JacocoCoverageVerification) {
    description = 'Verifies code coverage thresholds'
    group = 'verification'

    // Depend on all test tasks
    dependsOn(subprojects.test)

    // Get all JaCoCo execution data
    executionData {
        files(subprojects.jacocoTestReport.executionData)
    }

    // Define source files
    sourceDirectories.from = files(subprojects.sourceSets.main.allSource.srcDirs).files

    // Define class files
    classDirectories.from = files(subprojects.sourceSets.main.output).files

    // Add coverage threshold rules
    violationRules {
        rule {
            limit {
                minimum = 0.80 // 80% minimum coverage
            }
        }
    }
}

// Make sure the root report runs after all subproject reports
subprojects {
    jacocoTestReport {
        finalizedBy rootProject.tasks.named('jacocoRootReport')
    }
}

// Make sure coverage verification runs after the report
jacocoRootReport.finalizedBy jacocoCoverageVerification

check.dependsOn jacocoRootReport
