// Jenkins-Pipeline für den PDF KI Renamer
// Läuft auf einem Linux-Container (Synology NAS).
// Der MSI-Build ist Windows-only (jpackage + WiX Toolset 3.x). Jenkins läuft im
// Linux-Container auf Synology NAS und kann kein MSI erzeugen. Der MSI-Build
// wird bewusst manuell auf der Windows-Entwicklungsmaschine ausgeführt:
//   .\mvnw.cmd clean package -P release -pl pdf-umbenenner-packaging --also-make -DskipTests

pipeline {
    agent any

    options {
        disableConcurrentBuilds()
    }

    tools {
        maven 'maven-3'
    }

    // MAJOR und MINOR werden manuell als Jenkins-Parameter gepflegt.
    // BUILD_NUMBER wird automatisch durch Jenkins vergeben.
    // Die resultierende Versionsnummer lautet: MAJOR.MINOR.BUILD_NUMBER
    parameters {
        string(name: 'MAJOR', defaultValue: '3', description: 'SemVer MAJOR (manuell)')
        string(name: 'MINOR', defaultValue: '0', description: 'SemVer MINOR (manuell)')
    }

    stages {

        stage('Version bestimmen') {
            steps {
                script {
                    def isManual = !currentBuild.getBuildCauses('hudson.model.Cause$UserIdCause').isEmpty()
                    def jenkinsHome = env.JENKINS_HOME ?: '/var/jenkins_home'
                    def safeJobName = env.JOB_NAME.replaceAll(/[^A-Za-z0-9._-]/, '_')
                    def stateDir = "${jenkinsHome}/version-state"
                    def stateFile = "${stateDir}/${safeJobName}.properties"

                    if (isManual) {
                        env.EFFECTIVE_MAJOR = params.MAJOR
                        env.EFFECTIVE_MINOR = params.MINOR

                        sh """
                          mkdir -p '${stateDir}'
                          cat > '${stateFile}' <<'EOF'
MAJOR=${params.MAJOR}
MINOR=${params.MINOR}
EOF
                        """

                        echo "Manueller Build erkannt. Version gespeichert: ${env.EFFECTIVE_MAJOR}.${env.EFFECTIVE_MINOR}"
                    } else {
                        def stateExists = (sh(script: "[ -f '${stateFile}' ]", returnStatus: true) == 0)

                        if (stateExists) {
                            env.EFFECTIVE_MAJOR = sh(
                                script: "grep '^MAJOR=' '${stateFile}' | cut -d= -f2-",
                                returnStdout: true
                            ).trim()

                            env.EFFECTIVE_MINOR = sh(
                                script: "grep '^MINOR=' '${stateFile}' | cut -d= -f2-",
                                returnStdout: true
                            ).trim()

                            echo "Automatischer Build erkannt. Gespeicherte Version verwendet: ${env.EFFECTIVE_MAJOR}.${env.EFFECTIVE_MINOR}"
                        } else {
                            env.EFFECTIVE_MAJOR = params.MAJOR
                            env.EFFECTIVE_MINOR = params.MINOR

                            echo "Automatischer Build ohne gespeicherten Stand. Fallback auf Parameter: ${env.EFFECTIVE_MAJOR}.${env.EFFECTIVE_MINOR}"
                        }
                    }

                    currentBuild.displayName = "#${env.BUILD_NUMBER} ${env.EFFECTIVE_MAJOR}.${env.EFFECTIVE_MINOR}"
                }
            }
        } // stage: Version bestimmen

        stage('Maven Build') {
            steps {
                catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
                    // -Drevision übergibt die vollständige Versionsnummer an Maven.
                    // Das flatten-maven-plugin im Parent-POM löst ${revision} in
                    // allen installierten POMs auf.
                    sh "mvn clean verify -Drevision=${env.EFFECTIVE_MAJOR}.${env.EFFECTIVE_MINOR}.${env.BUILD_NUMBER}"
                }
            }
        } // stage: Maven Build

		stage('SonarQube Analyse') {
            steps {
                catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
                    withSonarQubeEnv('SonarQube') {
                        sh "mvn sonar:sonar -Drevision=${env.EFFECTIVE_MAJOR}.${env.EFFECTIVE_MINOR}.${env.BUILD_NUMBER} -Dsonar.projectKey=pdf-umbenenner -Dsonar.projectName='PDF KI Renamer' -Dsonar.branch.name=main"
                    }
                }
            }
        } // stage: SonarQube Analyse

        stage('Publish PIT Coverage') {
            steps {
                recordCoverage(
                    tools: [[
                        parser: 'PIT',
                        pattern: '**/target/pit-reports/mutations.xml'
                    ]],
                    id: 'pit',
                    name: 'PIT Mutation Coverage',
                    failOnError: true
                )
            }
        } // stage: Publish PIT Coverage

        stage('Archive JAR') {
            steps {
                // Bash wird explizit erzwungen, weil Jenkins-Agenten standardmäßig
                // sh (dash) verwenden, das kein mapfile kennt. mapfile zählt exakt
                // die gefundenen Shade-JARs und bricht ab, wenn nicht genau eines vorhanden ist.
                sh '''#!/usr/bin/env bash
set -euo pipefail

mapfile -t JARS < <(find pdf-umbenenner-bootstrap/target \
    -maxdepth 1 -name "pdf-umbenenner-bootstrap-*.jar" \
    ! -name "*-sources.jar" ! -name "*-javadoc.jar")

test "${#JARS[@]}" -eq 1 \
    || { echo "FEHLER: Erwartet genau 1 Shade-JAR, gefunden: ${#JARS[@]}"; exit 1; }

JAR_NAME="pdf-ki-renamer-${EFFECTIVE_MAJOR}.${EFFECTIVE_MINOR}.${BUILD_NUMBER}.jar"
cp "${JARS[0]}" "$JAR_NAME"
echo "Shade-JAR archiviert als: $JAR_NAME"
'''
                archiveArtifacts artifacts: 'pdf-ki-renamer-*.jar', fingerprint: true
            }
        } // stage: Archive JAR

        stage('Artefakt ablegen') {
            steps {
                sh '''#!/usr/bin/env bash
set -euo pipefail

BUILD_DIR="/builds/${EFFECTIVE_MAJOR}.${EFFECTIVE_MINOR}.${BUILD_NUMBER}"
mkdir -p "$BUILD_DIR"
cp pdf-ki-renamer-*.jar "$BUILD_DIR/"
echo "Artefakt abgelegt unter: $BUILD_DIR"
'''
            }
        } // stage: Artefakt ablegen

        stage('Berichte veröffentlichen') {
            steps {
                junit testResults: '**/target/surefire-reports/*.xml', allowEmptyResults: true

                recordCoverage(
                    tools: [[parser: 'JACOCO', pattern: 'pdf-umbenenner-coverage/target/site/jacoco-aggregate/jacoco.xml']],
                    enabledForFailure: true
                )

                publishHTML(target: [
                    reportName: 'JaCoCo HTML Report',
                    reportDir: 'pdf-umbenenner-coverage/target/site/jacoco-aggregate',
                    reportFiles: 'index.html',
                    keepAll: true,
                    alwaysLinkToLastBuild: true,
                    allowMissing: true
                ])
            }
        } // stage: Berichte veröffentlichen

        stage('Aufräumen') {
            steps {
                sh '''#!/usr/bin/env bash
set -euo pipefail
rm -f pdf-ki-renamer-*.jar
echo "Aufräumen abgeschlossen."
'''
            }
        } // stage: Aufräumen

    } // stages

    post {
        success {
            echo "Build ${env.EFFECTIVE_MAJOR}.${env.EFFECTIVE_MINOR}.${env.BUILD_NUMBER} erfolgreich abgeschlossen."
        }
        failure {
            echo "Build ${env.EFFECTIVE_MAJOR}.${env.EFFECTIVE_MINOR}.${env.BUILD_NUMBER} fehlgeschlagen."
        }
        always {
            deleteDir()
        }
    }

} // pipeline