// GUARDiA ITSM — Java Maven 표준 파이프라인
// 사용법: Jenkins → New Item → Pipeline → SCM → 이 파일 지정

pipeline {
    agent any

    tools {
        maven 'maven3'
        jdk   'JDK17'
    }

    parameters {
        string(name: 'ITSM_SESSION_ID', defaultValue: '', description: 'GUARDiA 바이브 세션 ID')
        string(name: 'ITSM_SR_ID',      defaultValue: '', description: '연결된 SR ID')
        choice(name: 'DEPLOY_ENV',      choices: ['dev', 'stg', 'prd'], description: '배포 환경')
        string(name: 'TARGET_SERVER',   defaultValue: '', description: '배포 대상 서버명')
        booleanParam(name: 'SKIP_TEST', defaultValue: false, description: '테스트 건너뜀')
    }

    environment {
        APP_VERSION     = "${env.BRANCH_NAME ?: 'unknown'}-${env.BUILD_NUMBER}"
        SCRIPTS_ROOT    = "${WORKSPACE}/cicd/scripts/pipeline"
        NOTIFY_SCRIPT   = "${WORKSPACE}/cicd/scripts/notify/itsm_callback.sh"
        ITSM_URL        = "${env.ITSM_URL ?: 'http://itsm.agency.go.kr:8000'}"
    }

    options {
        timeout(time: 90, unit: 'MINUTES')
        buildDiscarder(logRotator(numToKeepStr: '30', artifactNumToKeepStr: '10'))
        disableConcurrentBuilds()
        maskPasswords()
    }

    stages {
        stage('Checkout') {
            steps {
                // Gitea(온프레미스) → GitHub 순서로 SCM 폴백
                script {
                    def giteaUrl = "${env.GITEA_BASE_URL ?: 'http://localhost:3000'}/${env.GITEA_ORG ?: 'guardia'}/${env.GIT_REPO_NAME ?: 'GUARDiA'}.git"
                    try {
                        checkout([
                            $class: 'GitSCM',
                            branches: [[name: "*/${env.BRANCH_NAME ?: 'main'}"]],
                            userRemoteConfigs: [[
                                url: giteaUrl,
                                credentialsId: 'gitea-credentials'
                            ]],
                            extensions: [[$class: 'CloneOption', depth: 1, noTags: false, shallow: true]]
                        ])
                        echo "✅ Gitea checkout: ${env.GIT_COMMIT?.take(8) ?: 'N/A'}"
                    } catch (Exception e) {
                        echo "⚠️ Gitea checkout 실패 — SCM 기본값 사용: ${e.message}"
                        checkout scm
                    }
                }
            }
        }

        stage('Build') {
            steps {
                withCredentials([string(credentialsId: 'itsm-api-token', variable: 'ITSM_TOKEN')]) {
                    sh "bash ${NOTIFY_SCRIPT} BUILDING '빌드 시작'"
                }
                sh """
                    mvn clean package -DskipTests=true \
                        -Dapp.version=${APP_VERSION} \
                        --batch-mode --no-transfer-progress
                """
                echo "✅ 빌드 완료"
            }
            post {
                failure {
                    sh "bash ${NOTIFY_SCRIPT} FAILED '빌드 실패 (Stage: Build)' || true"
                }
            }
        }

        stage('Test') {
            when {
                expression { return !params.SKIP_TEST }
            }
            parallel {
                stage('Unit Test') {
                    steps {
                        sh """
                            mvn test \
                                --batch-mode --no-transfer-progress \
                                -Dapp.version=${APP_VERSION}
                        """
                    }
                    post {
                        always {
                            junit testResults: '**/target/surefire-reports/*.xml',
                                  allowEmptyResults: true
                        }
                    }
                }
                stage('SonarQube') {
                    when {
                        anyOf {
                            branch 'release/*'
                            branch 'main'
                        }
                    }
                    steps {
                        withSonarQubeEnv('sonarqube') {
                            sh """
                                mvn sonar:sonar \
                                    -Dsonar.projectVersion=${APP_VERSION} \
                                    --batch-mode --no-transfer-progress
                            """
                        }
                        timeout(time: 10, unit: 'MINUTES') {
                            waitForQualityGate abortPipeline: true
                        }
                    }
                }
            }
            post {
                failure {
                    sh "bash ${NOTIFY_SCRIPT} FAILED '테스트 실패 (Stage: Test)' || true"
                }
            }
        }

        stage('Archive') {
            steps {
                archiveArtifacts(
                    artifacts: 'target/*.jar,target/*.war',
                    fingerprint: true,
                    allowEmptyArchive: false
                )
                echo "✅ 아티팩트 저장 완료"
            }
        }

        stage('Production Approval') {
            when {
                anyOf {
                    branch 'main'
                    branch 'hotfix/*'
                }
                expression { return params.DEPLOY_ENV == 'prd' }
            }
            steps {
                withCredentials([string(credentialsId: 'itsm-api-token', variable: 'ITSM_TOKEN')]) {
                    sh "bash ${NOTIFY_SCRIPT} PENDING_APPROVAL '운영 배포 승인 대기 중'"
                }
                timeout(time: 30, unit: 'MINUTES') {
                    input message: "운영(prd) 배포를 승인하시겠습니까?",
                          ok: "배포 승인",
                          submitterParameter: "APPROVER"
                }
            }
        }

        stage('Deploy') {
            steps {
                withCredentials([string(credentialsId: 'itsm-api-token', variable: 'ITSM_TOKEN')]) {
                    sh "bash ${NOTIFY_SCRIPT} DEPLOYING '배포 시작'"
                }
                withCredentials([sshUserPrivateKey(
                    credentialsId: "ssh-${params.TARGET_SERVER}",
                    keyFileVariable: 'SSH_KEY',
                    usernameVariable: 'SSH_USER'
                )]) {
                    sh """
                        bash ${SCRIPTS_ROOT}/deploy.sh \
                            --server    "${params.TARGET_SERVER}" \
                            --env       "${params.DEPLOY_ENV}" \
                            --ssh-key   "${SSH_KEY}" \
                            --ssh-user  "${SSH_USER}" \
                            --artifact  "\$(ls target/*.jar target/*.war 2>/dev/null | head -1)"
                    """
                }
            }
            post {
                failure {
                    sh "bash ${NOTIFY_SCRIPT} FAILED '배포 실패 (Stage: Deploy)' || true"
                }
            }
        }

        stage('WAS Restart') {
            steps {
                withCredentials([sshUserPrivateKey(
                    credentialsId: "ssh-${params.TARGET_SERVER}",
                    keyFileVariable: 'SSH_KEY',
                    usernameVariable: 'SSH_USER'
                )]) {
                    sh """
                        bash ${SCRIPTS_ROOT}/was_restart.sh \
                            --server   "${params.TARGET_SERVER}" \
                            --ssh-key  "${SSH_KEY}" \
                            --ssh-user "${SSH_USER}" \
                            --was-type "${env.WAS_TYPE ?: 'tomcat'}"
                    """
                }
            }
            post {
                failure {
                    sh """
                        bash ${SCRIPTS_ROOT}/rollback.sh \
                            --server "${params.TARGET_SERVER}" \
                            --reason "WAS 재기동 실패" || true
                    """
                    sh "bash ${NOTIFY_SCRIPT} FAILED 'WAS 재기동 실패 — 롤백 시도' || true"
                }
            }
        }

        stage('Health Check') {
            steps {
                retry(3) {
                    sh """
                        bash ${SCRIPTS_ROOT}/health_check.sh \
                            --url     "${env.HEALTH_CHECK_URL ?: 'http://localhost:8080/health'}" \
                            --timeout 60 \
                            --retries 3
                    """
                }
            }
            post {
                failure {
                    sh """
                        bash ${SCRIPTS_ROOT}/rollback.sh \
                            --server "${params.TARGET_SERVER}" \
                            --reason "헬스체크 실패" || true
                    """
                    sh "bash ${NOTIFY_SCRIPT} ROLLED_BACK '헬스체크 실패 — 자동 롤백 완료' || true"
                }
            }
        }

        stage('ITSM Callback') {
            steps {
                sh """
                    bash ${NOTIFY_SCRIPT} COMPLETED \
                        "배포 완료 (빌드 #${env.BUILD_NUMBER}, ${params.DEPLOY_ENV})"
                """
            }
        }
    }

    post {
        always {
            cleanWs(cleanWhenAborted: true, cleanWhenFailure: true, cleanWhenSuccess: true)
        }
        success {
            echo "🎉 파이프라인 성공: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
        }
        failure {
            sh "bash ${NOTIFY_SCRIPT} FAILED '파이프라인 실패: ${env.JOB_NAME} #${env.BUILD_NUMBER}' || true"
        }
    }
}
