String GITHUB_REPOSITORY = 'scripts-vector'
String ECR_ACCOUNT_ID = '086679231553'
List<String> AWS_REGIONS = ['us-east-1']
String SLACK_NOTIFICATIONS_CHANNEL = '#distro-build-alerts'
String QA_ACCOUNT_ID = '437795906767'
String QA_DEPLOYMENT_ROLE = 'prod-jenkins-aws-pipeline-agent'
String PROD_ACCOUNT_ID = '437795906767'
String PROD_DEPLOYMENT_ROLE = 'prod-jenkins-aws-pipeline-agent'

TASK_CONFIG = [
    'cancel-backlog-for-store': [
        test: true,
        build: true,
        deployType: null,
        language: 'python',
        softwareCatalog: false,
        vulnerabilitiesToIgnore: [],
    ],
    'clear-delivery-history': [
        test: true,
        build: true,
        deployType: null,
        language: 'python',
        softwareCatalog: false,
        vulnerabilitiesToIgnore: [],
    ],
    'direct_delivery_update': [
        test: true,
        build: true,
        deployType: 'UPDATE_CLOUDWATCH_EVENT',
        language: 'php',
        softwareCatalog: true,
        vulnerabilitiesToIgnore: [],
    ],
    'distro-bug-monitoring': [
        test: true,
        build: true,
        deployType: null,
        language: 'python',
        softwareCatalog: false,
        vulnerabilitiesToIgnore: [],
    ],
    'dolby-atmos-packager-alpha': [
        test: true,
        build: true,
        deployType: 'CREATE_TASK_DEFINITION',
        language: 'python',
        softwareCatalog: true,
        vulnerabilitiesToIgnore: [],
    ],
    'gras_delivery': [
        test: true,
        build: true,
        deployType: 'UPDATE_CLOUDWATCH_EVENT',
        language: 'php',
        softwareCatalog: true,
        vulnerabilitiesToIgnore: ['CVE-2025-13836', 'CVE-2025-8194'],
    ],
    'product-store-eligibility-check': [
        test: true,
        build: false,
        deployType: null,
        language: 'python',
        softwareCatalog: false,
        vulnerabilitiesToIgnore: [],
    ],
    'xml-generator': [
        test: true,
        build: true,
        deployType: null,
        language: 'python',
        softwareCatalog: false,
        vulnerabilitiesToIgnore: [],
    ],
    'sound-recordings-takedown': [
        test: true,
        build: true,
        deployType: 'UPDATE_CLOUDWATCH_EVENT',
        language: 'python',
        softwareCatalog: true,
        vulnerabilitiesToIgnore: ['CVE-2026-3805'],
    ],
]

pipeline {
    agent none

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

    parameters {
        booleanParam(
            name: 'DEPLOY_TO_PROD',
            defaultValue: true,
            description: 'Whether or not to deploy to prod.'
        )
        string(
            name: 'TASK_NAMES',
            defaultValue: '',
            description: 'Comma-separated list of directories to build. If not specified, all modified directories will be built.'
        )
        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') {
            agent any
            steps {
                complianceChecks()
            }
        }
        stage('Validate Software Catalog Definitions') {
            steps {
                withModifiedProjects(checkout: true) { project, config ->
                    script {
                        if (config.softwareCatalog == true) {
                            datadogSoftwareCatalogValidate(servicePath: project)
                        } else {
                            echo "No software catalog definition configured for project: ${project}"
                        }
                    }

                }
            }
        }
        stage('Static Application Security Tests') {
            steps {
                withModifiedProjects(checkout: true) { project, config ->
                    sastTests(projectDir: project)
                }
            }
        }

        stage('Unit Tests and Style Checks') {
            steps {
                withModifiedProjects(checkout: true) { project, config ->
                    withEnv(["COMPOSE_PROJECT_NAME=${env.BUILD_TAG.toLowerCase()}-${project.replaceAll('/', '-')}"]) {
                        withCredentials([string(credentialsId: 'composer-github-auth', variable: 'COMPOSER_AUTH'),]) {
                            withEcr {
                                script {
                                    if (config.test == true) {
                                        dir(project) {
                                            try {
                                                sh "docker compose run --rm --build lint-and-test"
                                            }
                                            finally {
                                                sh 'docker compose down --remove-orphans'
                                            }
                                        }
                                    } else {
                                        echo "No unit tests or style checks configured for project: ${project}"
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        stage('Sonar Scan and Analysis') {
            when {
                branch 'master'
            }
            steps {
                withModifiedProjects(checkout: true) { project, config ->
                    sonarScan project: "${GITHUB_REPOSITORY}-${project.replaceAll('_', '-')}",
                        language: config.language,
                        projectBaseDir: project
                }
            }
        }
        stage('Create a Release') {
            when {
                anyOf {
                    branch 'master'
                    expression { env.GITHUB_COMMENT =~ 'build docker' }
                }
            }
            steps {
                withModifiedProjects(checkout: true) { project, config ->
                    script {
                        if (config.build == true) {
                            withCredentials([string(credentialsId: 'composer-github-auth', variable: 'COMPOSER_AUTH'),]) {
                                dockerToEcr awsRegions: AWS_REGIONS,
                                    ecrAccountId: ECR_ACCOUNT_ID,
                                    imageName: project.replaceAll('_', '-'),
                                    imageTag: env.GIT_COMMIT,
                                    dockerBuildContext: project,
                                    dockerBuildFile: "${project}/Dockerfile",
                                    dockerBuildSecrets: [[id: 'COMPOSER_AUTH', env: 'COMPOSER_AUTH']], // TODO: only set this when needed
                                    dockerBuildTarget: 'app'
                            }
                        } else {
                            echo "No build configured for project: ${project}"
                        }
                    }
                }
            }
        }
        stage('Deploy to QA') {
            when {
                branch 'master'
            }
            steps {
                withModifiedProjects(checkout: true) { project, config ->
                    script {
                        if (config.deployType != null) {
                            fargateDeploy awsRegions: AWS_REGIONS,
                                gitCommit: env.GIT_COMMIT,
                                serviceName: project.replaceAll('_', '-'),
                                ecrRegistryAccountId: ECR_ACCOUNT_ID,
                                environment: 'qa',
                                deployType: config.deployType,
                                awsDeploymentTargetAccountId: QA_ACCOUNT_ID,
                                awsDeploymentRoleName: QA_DEPLOYMENT_ROLE
                        } else {
                            echo "No deployment configured for project: ${project}"
                        }
                    }
                }
            }
        }
        stage('Scan Docker Image') {
            when {
                anyOf {
                    branch 'master'
                    expression { env.GITHUB_COMMENT =~ 'build docker' }
                }
            }
            steps {
                withModifiedProjects(checkout: true) { project, config ->
                    script {
                        if (config.build == true) {
                            dockerScan awsRegion: AWS_REGIONS[0],
                                ecrAccountId: ECR_ACCOUNT_ID,
                                imageName: project.replaceAll('_', '-'),
                                imageTag: env.GIT_COMMIT,
                                vulnerabilitiesToIgnore: config.vulnerabilitiesToIgnore
                        } else {
                            echo "No build configured for project: ${project}"
                        }
                    }
                }
            }
        }
        stage('Deploy to Prod') {
            when {
                allOf {
                    branch 'master'
                    expression { params.DEPLOY_TO_PROD }
                }
            }
            steps {
                withModifiedProjects(checkout: true) { project, config ->
                    script {
                        if (config.deployType != null) {
                            fargateDeploy awsRegions: AWS_REGIONS,
                                gitCommit: env.GIT_COMMIT,
                                serviceName: project.replaceAll('_', '-'),
                                ecrRegistryAccountId: ECR_ACCOUNT_ID,
                                environment: 'prod',
                                deployType: config.deployType,
                                awsDeploymentTargetAccountId: PROD_ACCOUNT_ID,
                                awsDeploymentRoleName: PROD_DEPLOYMENT_ROLE
                        } else {
                            echo "No build configured for project: ${project}"
                        }
                        if (config.softwareCatalog == true) {
                            datadogSoftwareCatalogPublish(servicePath: project)
                        }
                    }
                }
            }
        }
    }

    post {
        regression {
            script {
                if (env.BRANCH_NAME == 'master') {
                    slackNotify channel: SLACK_NOTIFICATIONS_CHANNEL
                }
            }
        }
        fixed {
            script {
                if (env.BRANCH_NAME == 'master') {
                    slackNotify channel: SLACK_NOTIFICATIONS_CHANNEL
                }
            }
        }
    }
}

def withModifiedProjects(Map args = [:], Closure steps) {
    getMonorepoUtils().withModifiedProjects(args, steps)
}

def getMonorepoUtils() {
    return library("jenkins-global-libraries@${params.SHARED_LIBRARIES_VERSION}").com.sonymusic.MonorepoUtils.getInstance(
        steps: this,
        projectConfig: TASK_CONFIG,
        projectsToBuild: params.TASK_NAMES ? params.TASK_NAMES.split(',') : null
    )
}
