String GITHUB_REPOSITORY = 'dra-dispatcher-service'
String ECR_ACCOUNT_ID = '086679231553'
List<String> AWS_REGIONS = ['us-east-1', 'eu-central-1']
String SLACK_NOTIFICATIONS_CHANNEL = '#digsys-dra'
String DEV_ACCOUNT_ID = '718729873097'
String DEV_DEPLOYMENT_ROLE = 'dev-jenkins-pipeline-deploy-role'
String PROD_ACCOUNT_ID = '799833541840'
String PROD_DEPLOYMENT_ROLE = 'prod-jenkins-pipeline-deploy-role'

pipeline {
    agent any    

    options {
        ansiColor('xterm')
        disableConcurrentBuilds()
        timestamps()
    }

    parameters {
        booleanParam(name: 'DEPLOY_TO_PROD', defaultValue: false, description: 'Whether or not to deploy to prod.')
        string(name: 'SHARED_LIBRARIES_VERSION', defaultValue: 'master', description: 'The version of the Jenkins shared libraries to use. Can be a branch, tag or Git revision.')
    }

    triggers {
        issueCommentTrigger('.*retest this please.*')
    }

    stages {
        stage('Load Shared Libraries') {
            steps {
                library "jenkins-global-libraries@${params.SHARED_LIBRARIES_VERSION}"
            }
        }

        stage('Compliance Checks') {
            steps {
                complianceChecks()
            }
        }

        stage('Validate Software Catalog Definition') {
            steps {
                datadogSoftwareCatalogValidate()
            }
        }

        stage('Tests') {
            parallel {
                stage('Unit Tests and Style Checks') {
                    steps {
                        withEcr {
                            script {
                                runDockerTests('unit-tests')
                            }
                        }
                    }
                    post {
                        success {
                            junit testResults: 'reports/surefire-reports/TEST-*.xml'
                            recordCoverage(tools: [[parser: 'JACOCO', pattern: 'reports/jacoco/jacoco.xml']], enabledForFailure: true, failOnError: false, sourceDirectories: [[path: "src/main/java"]])
                        }
                    }
                }
                
                stage('Static Application Security Tests') {
                    steps {
                        sastTests()
                    }
                }
            }
        }

        stage('Sonar Scan and Analysis') {
            when {
               branch 'master'
            }
            steps {     
                sonarScan(
                    project: GITHUB_REPOSITORY,
                    language: 'java',
                    exclusions: 'src/test/**,target/**,reports/**,test_scripts/**',
                    additionalProperties: [
                        'sonar.java.binaries': "${env.WORKSPACE}/sonar-classes",
                        'sonar.coverage.jacoco.xmlReportPaths': "${env.WORKSPACE}/reports/jacoco/jacoco.xml"
                    ]
                )
                              
            }
        }


        stage('Create a Release') {
            when {
                branch 'master'
            }
            steps {                
                    dockerToEcr awsRegions: [AWS_REGIONS[0]], ecrAccountId: ECR_ACCOUNT_ID, imageName: GITHUB_REPOSITORY, imageTag: env.GIT_COMMIT
            }
        }

        

        stage('Scan Docker Image') {
            when {
                branch 'master'
            }
            steps {
                dockerScan awsRegion: AWS_REGIONS[0], ecrAccountId: ECR_ACCOUNT_ID, imageName: GITHUB_REPOSITORY, imageTag: env.GIT_COMMIT,
                    failBuild: true
            }
        }

        stage('Deploy to DEV') {
            when {
                branch 'master'
            }
            steps {
                fargateDeploy environment: 'dev', awsRegions: [AWS_REGIONS[1]], gitCommit: env.GIT_COMMIT, forceScaleOut:true, serviceName: GITHUB_REPOSITORY,
                    ecrRegistryAccountId: ECR_ACCOUNT_ID, awsDeploymentTargetAccountId: DEV_ACCOUNT_ID, awsDeploymentRoleName: DEV_DEPLOYMENT_ROLE
            }
        }        

        /* 
        
        Uncomment the below stages when ready to run integration and E2E tests in the pipeline. Make sure to set up the necessary infrastructure, 
        such as test clusters and test accounts, before doing so.

        stage('Integration Tests') {
            when {
                branch 'master'
            }
            steps {
                withEcr {
                    withAWS(role: INTEGRATION_TEST_ROLE, roleAccount: ACCOUNT_ID, roleSessionName: SESSION_NAME, useNode: true) {
                        script {
                            runDockerTests('integration-tests')
                        }
                    }
                }
            }
        }
        stage('E2E Tests') {
            when {
                branch 'master'
            }
            environment {
                TAGS = "@${GITHUB_REPOSITORY.replaceAll('-', '_')}"
            }
            steps {
                playwrightTests tags: env.TAGS
            }
        }

        

        stage('Deploy to Prod') {
            when {
                allOf {
                    branch 'master'
                    expression { params.DEPLOY_TO_PROD }
                }
            }
            steps {
                fargateDeploy environment: 'prod', awsRegions: [AWS_REGIONS[1]], gitCommit: env.GIT_COMMIT, serviceName: GITHUB_REPOSITORY,
                    ecrRegistryAccountId: ECR_ACCOUNT_ID, awsDeploymentTargetAccountId: PROD_ACCOUNT_ID, awsDeploymentRoleName: PROD_DEPLOYMENT_ROLE
            }
        }
        */
        stage('Publish Software Catalog Definition') {
            when {
                allOf {
                    branch 'master'
                    expression { params.DEPLOY_TO_PROD }
                }
            }
            steps {
                datadogSoftwareCatalogPublish()
            }
        }
    }

    post {
        always {
            script {
                if (env.BRANCH_NAME == 'master') {
                    slackNotify channel: SLACK_NOTIFICATIONS_CHANNEL
                }
            }
        }
        cleanup {
            cleanWs()
        }
    }
}

def runDockerTests(String profileName) {
    echo "Starting Docker Compose tests for profile: ${profileName}"
    def projectName = "${env.BUILD_TAG}-${profileName}".toLowerCase()

    try {
        sh """
            docker compose \
                -p "${projectName}" \
                --profile "${profileName}" \
                run \
                --rm \
                --build \
                "${profileName}"
        """
    } finally {
        echo "Cleaning up Docker resources for ${profileName}..."
        sh """
            docker compose \
                -p "${projectName}" \
                down --rmi local --remove-orphans
        """
    }
}
