String HOST_01 = 'prod-jenkins-sme-madison-osx-agent01'
String HOST_02 = 'prod-jenkins-sme-madison-osx-agent02'
String HOST_03 = 'prod-jenkins-sme-madison-osx-agent03'
String HOST_OSX_AGENTS = 'osx-agents'
String HOST_LINUX = 'linux'

def utils
def lib

pipeline {
    agent {
        label params.HOST
    }

    options {
        ansiColor('xterm')
        timestamps()
        throttleJobProperty(
            categories: [],
            limitOneJobWithMatchingParams: false,
            maxConcurrentPerNode: 1,
            maxConcurrentTotal: 0,
            paramsToUseForLimit: '',
            throttleEnabled: true,
            throttleOption: 'project'
        )
    }

    parameters {
        choice(
            name: 'HOST',
            choices: [
                HOST_LINUX,
                HOST_OSX_AGENTS,
                HOST_01,
                HOST_02,
                HOST_03,
            ],
            description: 'HOST')
        string(
            name: 'GIT_COMMIT',
            defaultValue: '',
            description: 'Commit version to checkout and build bundle to.')
        string(
            name: 'AWS_BINARIES_NAME_PREFIX',
            defaultValue: '',
            description: 'AWS Binaries Name Prefix')
        choice(
            name: 'BRAND',
            choices: ['orchard', 'awal', 'sme'],
            description: 'Brand')
        choice(
            name: 'PLATFORM',
            choices: ['ios', 'android', 'iosSimulator'],
            description: 'Platform')
        choice(
            name: 'ENVIRONMENT',
            choices: ['prod', 'qa', 'dev'],
            description: 'Environment')
        choice(
            name: 'STORE',
            choices: ['s3', 'store'],
            description: 'Store')
        choice(
            name: 'ANDROID_BINARY_TYPE',
            choices: ['apk', 'aab'],
            description: 'Android binary type')
        string(
            name: 'PROD_LOG_TO_SENTRY',
            defaultValue: 'true',
            description: 'Log to Sentry')
        choice(
            name: 'PROD_CODE_PUSH_ENABLED',
            choices: ['true', 'false'],
            description: 'Code Push Enabled')
        choice(
            name: 'PROD_DATADOG_ENABLED',
            choices: ['true', 'false'],
            description: 'Datadog Enabled')
        string(
            name: 'QA_LOG_TO_SENTRY',
            defaultValue: 'true',
            description: 'Log to Sentry')
        choice(
            name: 'QA_CODE_PUSH_ENABLED',
            choices: ['false', 'true'],
            description: 'Code Push Enabled')
        choice(
            name: 'QA_DATADOG_ENABLED',
            choices: ['false', 'true'],
            description: 'Datadog Enabled')
    }

    environment {
        // override PATH to include /usr/local/bin
        PATH = "${sh (script: 'echo "/usr/local/bin:${PATH}"', returnStdout: true)}"
    }

    stages {
        stage('Initialize') {
            environment {
                AWS_ACCOUNT_ID = '437795906767'
                AWS_ROLE_NAME = 'jenkins-mac-mini-agent'
            }
            steps {
                script {
                    checkout([
                        $class: 'GitSCM',
                        branches: [[name: params.GIT_COMMIT]],
                        doGenerateSubmoduleConfigurations: false,
                        extensions: [],
                        submoduleCfg: [],
                        userRemoteConfigs: [[
                            credentialsId: '577cbc72-7d9e-4eba-924c-ecbbe6de9805',
                            url: 'git@github.com:theorchard/orchardgo.git'
                        ]]
                    ])
                    shared = load './jenkins/shared.groovy'
                    shared.initGitSha(params.GIT_COMMIT)

                    // Load Utils from the shared library
                    lib = library(shared.library())
                    utils = lib.com.sonymusic.Utils.new(this)

                    // Use the AWS credentials to assume the role
                    withCredentials([[
                        $class: 'AmazonWebServicesCredentialsBinding',
                        credentialsId: 'jenkins-mac-mini-agent',
                        accessKeyVariable: 'AWS_ACCESS_KEY_ID',
                        secretKeyVariable: 'AWS_SECRET_ACCESS_KEY'
                    ]]) {
                        // Assume the role
                        def assumeRoleCommand = """
                            aws sts assume-role \
                            --role-arn arn:aws:iam::${AWS_ACCOUNT_ID}:role/${AWS_ROLE_NAME} \
                            --role-session-name ${NODE_NAME}
                        """
                        def assumeRoleResult = sh(script: assumeRoleCommand, returnStdout: true)
                        def credentials = readJSON text: assumeRoleResult

                        // Export temporary credentials
                        env.AWS_ACCESS_KEY_ID = credentials.Credentials.AccessKeyId
                        env.AWS_SECRET_ACCESS_KEY = credentials.Credentials.SecretAccessKey
                        env.AWS_SESSION_TOKEN = credentials.Credentials.SessionToken
                        env.AWS_DEFAULT_REGION = 'us-east-1'
                    }
                }
            }
        }
        stage('Prepare Environment') {
            steps {
                script {
                    def secretNames = [
                        'POEDITOR_API_TOKEN',
                        'PACKAGECLOUD_TOKEN',
                        'GITHUB_TOKEN',
                        'CODE_PUSH_STANDALONE_ACCESS_KEY',
                        'SENTRY_AUTH_TOKEN',
                        'ORCHARD_APP_STORE_CERTIFICATE_PASSWORD',
                        'ORCHARD_APP_STORE_API_KEY_ID',
                        'ORCHARD_APP_STORE_API_KEY_ISSUER_ID',
                        'AWAL_APP_STORE_API_KEY_ID',
                        'AWAL_APP_STORE_API_KEY_ISSUER_ID',
                        'AWAL_APP_STORE_CERTIFICATE_PASSWORD',
                        'SME_APP_STORE_API_KEY_ID',
                        'SME_APP_STORE_API_KEY_ISSUER_ID',
                        'SME_APP_STORE_CERTIFICATE_PASSWORD',
                        'ORCHARD_PROD_GOOGLE_PLAY_KEYSTORE_FILE_PASSWORD',
                        'ORCHARD_PROD_GOOGLE_PLAY_KEYSTORE_KEY_ALIAS',
                        'ORCHARD_PROD_GOOGLE_PLAY_KEYSTORE_KEY_PASSWORD',
                        'ORCHARD_QA_GOOGLE_PLAY_KEYSTORE_FILE_PASSWORD',
                        'ORCHARD_QA_GOOGLE_PLAY_KEYSTORE_KEY_ALIAS',
                        'ORCHARD_QA_GOOGLE_PLAY_KEYSTORE_KEY_PASSWORD',
                        'ORCHARD_DEV_GOOGLE_PLAY_KEYSTORE_FILE_PASSWORD',
                        'ORCHARD_DEV_GOOGLE_PLAY_KEYSTORE_KEY_ALIAS',
                        'ORCHARD_DEV_GOOGLE_PLAY_KEYSTORE_KEY_PASSWORD',
                        'AWAL_PROD_GOOGLE_PLAY_KEYSTORE_FILE_PASSWORD',
                        'AWAL_PROD_GOOGLE_PLAY_KEYSTORE_KEY_ALIAS',
                        'AWAL_PROD_GOOGLE_PLAY_KEYSTORE_KEY_PASSWORD',
                        'AWAL_QA_GOOGLE_PLAY_KEYSTORE_FILE_PASSWORD',
                        'AWAL_QA_GOOGLE_PLAY_KEYSTORE_KEY_ALIAS',
                        'AWAL_QA_GOOGLE_PLAY_KEYSTORE_KEY_PASSWORD',
                        'SME_PROD_GOOGLE_PLAY_KEYSTORE_FILE_PASSWORD',
                        'SME_PROD_GOOGLE_PLAY_KEYSTORE_KEY_ALIAS',
                        'SME_PROD_GOOGLE_PLAY_KEYSTORE_KEY_PASSWORD',
                        'SME_QA_GOOGLE_PLAY_KEYSTORE_FILE_PASSWORD',
                        'SME_QA_GOOGLE_PLAY_KEYSTORE_KEY_ALIAS',
                        'SME_QA_GOOGLE_PLAY_KEYSTORE_KEY_PASSWORD',
                        'PROD_SEGMENT_IOS_WRITE_KEY',
                        'PROD_SEGMENT_ANDROID_WRITE_KEY',
                        'PROD_CODE_PUSH_ANDROID_DEPLOYMENT_KEY',
                        'PROD_CODE_PUSH_IOS_DEPLOYMENT_KEY',
                        'PROD_IOS_INTERCOM_API_KEY',
                        'PROD_ANDROID_INTERCOM_API_KEY',
                        'PROD_DATADOG_CLIENT_TOKEN',
                        'PROD_DATADOG_APPLICATION_ID',
                        'QA_SEGMENT_IOS_WRITE_KEY',
                        'QA_SEGMENT_ANDROID_WRITE_KEY',
                        'QA_CODE_PUSH_ANDROID_DEPLOYMENT_KEY',
                        'QA_CODE_PUSH_IOS_DEPLOYMENT_KEY',
                        'QA_IOS_INTERCOM_API_KEY',
                        'QA_ANDROID_INTERCOM_API_KEY',
                        'QA_DATADOG_CLIENT_TOKEN',
                        'QA_DATADOG_APPLICATION_ID'
                    ]
                    secretNames.each { secretName ->
                        def secretValue = utils.getSecretValue("prod/orchardgo/${secretName}")
                        env."${secretName}" = secretValue
                    }
                }
            }
        }
        stage('Build') {
            environment {
                // clean up AWS credentials previously set by assume-role
                AWS_ACCESS_KEY_ID = ''
                AWS_SECRET_ACCESS_KEY = ''
                AWS_SESSION_TOKEN = ''

                // Set environment variables from the parameters
                AWS_BINARIES_NAME_PREFIX = "${params.AWS_BINARIES_NAME_PREFIX}"
                BRAND = "${params.BRAND}"
                PLATFORM = "${params.PLATFORM}"
                ENVIRONMENT = "${params.ENVIRONMENT}"
                STORE = "${params.STORE}"
                ANDROID_BINARY_TYPE = "${params.ANDROID_BINARY_TYPE}"

                // Prod environment params
                PROD_LOG_TO_SENTRY = "${params.PROD_LOG_TO_SENTRY}"
                PROD_CODE_PUSH_ENABLED = "${params.PROD_CODE_PUSH_ENABLED}"
                PROD_DATADOG_ENABLED = "${params.PROD_DATADOG_ENABLED}"

                // QA environment params
                QA_LOG_TO_SENTRY = "${params.QA_LOG_TO_SENTRY}"
                QA_CODE_PUSH_ENABLED = "${params.QA_CODE_PUSH_ENABLED}"
                QA_DATADOG_ENABLED = "${params.QA_DATADOG_ENABLED}"

                AWS_REGION = 'us-east-1'
                AWS_BUCKET = 'orcd-mobile-binaries'

                POEDITOR_PROJECT_ID = '212659'

                INTERCOM_APP_ID = 'd3zzqrsd'

                SENTRY_ORGANIZATION_NAME = 'the-orchard'

                APP_STORE_PROFILE_FILE = 'OrchardGo_Jenkins_Distribution_Profile_Prod'

                ORCHARD_APP_STORE_TEAM_ID = '4T2W2RCFT2'
                ORCHARD_APP_STORE_CERTIFICATE_FILE = 'OrchardGo_Apple_Distribution_Cert'
                ORCHARD_APP_STORE_API_KEY_FILE = 'orchardgo-binary-deploy-prod-api-key'
                ORCHARD_APP_STORE_CERTIFICATE_SIGNING_IDENTITY_NAME = 'Apple Distribution: ORCHARD ENTERPRISES NY, INC (4T2W2RCFT2)'
                ORCHARD_GOOGLE_PLAY_JSON_FILE = 'GOOGLE_PLAY_JSON_FILE'

                AWAL_APP_STORE_TEAM_ID = '4T2W2RCFT2'
                AWAL_APP_STORE_API_KEY_FILE = 'orchardgo-binary-deploy-prod-api-key'
                AWAL_APP_STORE_CERTIFICATE_FILE = 'OrchardGo_Apple_Distribution_Cert'
                AWAL_APP_STORE_CERTIFICATE_SIGNING_IDENTITY_NAME = 'Apple Distribution: ORCHARD ENTERPRISES NY, INC (4T2W2RCFT2)'
                AWAL_GOOGLE_PLAY_JSON_FILE = 'GOOGLE_PLAY_JSON_FILE'

                SME_APP_STORE_TEAM_ID = 'PYHJN9Z6W2'
                SME_APP_STORE_API_KEY_FILE = 'smego-binary-deploy-prod-api-key'
                SME_APP_STORE_CERTIFICATE_FILE = 'SME_APP_STORE_CERTIFICATE_FILE'
                SME_APP_STORE_CERTIFICATE_SIGNING_IDENTITY_NAME = 'Apple Distribution: Sony Music Entertainment (PYHJN9Z6W2)'
                SME_GOOGLE_PLAY_JSON_FILE = 'SME_GOOGLE_PLAY_JSON_FILE'

                // Orchard Prod environment secrets
                ORCHARD_PROD_GOOGLE_PLAY_KEYSTORE_FILE = 'PROD_GOOGLE_PLAY_KEYSTORE_FILE'
                ORCHARD_PROD_STORE_APP_STORE_PROFILE_FILE = 'OrchardGo_Jenkins_Distribution_Profile_Prod'
                ORCHARD_PROD_S3_APP_STORE_PROFILE_FILE = 'OrchardGo_Jenkins_AdHoc_Profile_Prod.mobileprovision'

                // Orchard QA environment secrets
                ORCHARD_QA_GOOGLE_PLAY_KEYSTORE_FILE = 'androidQA.keystore'
                ORCHARD_QA_STORE_APP_STORE_PROFILE_FILE = 'OrchardGo_Jenkins_Distribution_Profile_QA'
                ORCHARD_QA_S3_APP_STORE_PROFILE_FILE = 'OrchardGo_Jenkins_AdHoc_Distribution_Profile_QA.mobileprovision'

                // Orchard Dev environment secrets
                ORCHARD_DEV_GOOGLE_PLAY_KEYSTORE_FILE = 'androidDev.keystore'
                ORCHARD_DEV_STORE_APP_STORE_PROFILE_FILE = 'OrchardGo_Jenkins_Distribution_Profile_Dev'
                ORCHARD_DEV_S3_APP_STORE_PROFILE_FILE = 'OrchardGo_Jenkins_AdHoc_Profile_Dev.mobileprovision'

                // AWAL Prod environment secrets
                AWAL_PROD_GOOGLE_PLAY_KEYSTORE_FILE = 'androidAwalProd.keystore'
                AWAL_PROD_STORE_APP_STORE_PROFILE_FILE = 'AWAL_Jenkins_Distribution_Profile_Prod'
                AWAL_PROD_S3_APP_STORE_PROFILE_FILE = 'AWAL_Jenkins_AdHoc_Profile_Prod.mobileprovision'

                // AWAL QA environment secrets
                AWAL_QA_GOOGLE_PLAY_KEYSTORE_FILE = 'androidAwalQA.keystore'
                AWAL_QA_STORE_APP_STORE_PROFILE_FILE = 'AWAL_Jenkins_Distribution_Profile_QA'
                AWAL_QA_S3_APP_STORE_PROFILE_FILE = 'AWAL_Jenkins_AdHoc_Profile_QA.mobileprovision'

                // AWAL Dev environment secrets
                AWAL_DEV_STORE_APP_STORE_PROFILE_FILE = 'AWAL_Jenkins_Distribution_Profile_QA'

                // SME Prod environment secrets
                SME_PROD_GOOGLE_PLAY_KEYSTORE_FILE = 'SME_PROD_GOOGLE_PLAY_KEYSTORE_FILE.keystore'
                SME_PROD_STORE_APP_STORE_PROFILE_FILE = 'SmeGo_Jenkins_Distribution_Profile_Prod'
                SME_PROD_S3_APP_STORE_PROFILE_FILE = 'SmeGo_Jenkins_AdHoc_Profile_Prod.mobileprovision'

                // SME QA environment secrets
                SME_QA_GOOGLE_PLAY_KEYSTORE_FILE = 'SME_QA_GOOGLE_PLAY_KEYSTORE_FILE.keystore'
                SME_QA_STORE_APP_STORE_PROFILE_FILE = 'OrchardGo_Jenkins_Distribution_Profile_QA'
                SME_QA_S3_APP_STORE_PROFILE_FILE = 'SmeGo_Jenkins_AdHoc_Distribution_Profile_QA.mobileprovision'

                // SME Dev environment secrets
                SME_DEV_STORE_APP_STORE_PROFILE_FILE = 'OrchardGo_Jenkins_Distribution_Profile_Dev'

                // Prod environment variables
                PROD_GRAPHQL_BASE = 'https://ows-grass.theorchard.io/graphql-router/graphql'
                PROD_SENTRY_PROJECT_NAME = 'mobile-orchard'
                PROD_SENTRY_DSN = 'https://cdfb6f5ec0f94d47a90b25236bbc72e0@o22178.ingest.sentry.io/1226561'
                PROD_INTERCOM_APP_ID = 'd3zzqrsd'

                // QA environment variables
                QA_GRAPHQL_BASE = 'https://qa-ows-grass.theorchard.io/graphql-router/graphql'
                QA_SENTRY_PROJECT_NAME = 'qa-mobile-orchard'
                QA_SENTRY_DSN = 'https://e04f634e77114e52b2e1016f625e9e06@o22178.ingest.sentry.io/1226562'
                QA_INTERCOM_APP_ID = 'zb83yhd0'
            }
            stages {
                stage('IOS') {
                    when {
                        expression { params.PLATFORM == 'ios' || params.PLATFORM == 'iosSimulator' }
                    }
                    steps {
                        script {
                            shared.withCommonCredential {
                                echo "Building binaries for ${BRAND} ${PLATFORM} ${ENVIRONMENT} ${STORE}"
                                sh label: 'Build binaries', script: './jenkins/build-binaries.sh'
                            }
                        }
                    }
                }
                stage('Android MacOS') {
                    when {
                        expression { params.PLATFORM == 'android' && params.HOST != HOST_LINUX }
                    }
                    steps {
                        script {
                            shared.withCommonCredential {
                                echo "Building Android binary for ${BRAND} ${PLATFORM} ${ENVIRONMENT} ${STORE} ${ANDROID_BINARY_TYPE}"
                                sh label: 'Build binaries', script: './jenkins/build-binaries.sh'
                            }
                        }
                    }
                }
                stage('Android Docker') {
                    when {
                        expression { params.PLATFORM == 'android' && params.HOST == HOST_LINUX }
                    }
                    steps {
                        script {
                            def dockerfileSha = sh(
                                script: 'shasum Dockerfile',
                                returnStdout: true
                            ).trim().take(8)
                            echo "Dockerfile SHA: ${dockerfileSha}"
                            if (!dockerfileSha) {
                                error('Dockerfile SHA is empty. Failing the build.')
                            }

                            def lockName = "orchardgo-android-docker-${env.NODE_NAME}"
                            echo "Lock name: ${lockName}"

                            def imageTag = "orchardgo-android-binary-box:${dockerfileSha}"
                            echo "Image tag: ${imageTag}"

                            lock(resource: lockName, inversePrecedence: true) {
                                withEcr {
                                    sh label: 'Pull Docker Image', script: 'docker pull 086679231553.dkr.ecr.us-east-1.amazonaws.com/docker-parent-images:ruby32'
                                    sh label: 'Build Docker Image', script: "docker build --target orchardgo --tag ${imageTag} -f ./Dockerfile ."
                                }
                            }
                            shared.withCommonCredential {
                                docker.image(imageTag).inside('-u root:root') {
                                    echo "Building Android binary for ${BRAND} ${PLATFORM} ${ENVIRONMENT} ${STORE} ${ANDROID_BINARY_TYPE}"
                                    sh label: 'Configure Git Safe Directory', script: 'git config --global --add safe.directory "*"'
                                    sh label: 'Build binaries', script: './jenkins/build-binaries.sh'
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    post {
        always {
            cleanWs(notFailBuild: true)
        }
    }
}
