def AWS_ACCOUNT_IDS_BY_NAME = getAwsAccountsMap()
def AWS_ACCOUNT_NAMES = AWS_ACCOUNT_IDS_BY_NAME.keySet() as List
AWS_ACCOUNT_NAMES = ['prod'] + (AWS_ACCOUNT_NAMES - ['prod']) // Ensure 'prod' is first in the list to make it the default choice

DEPLOYMENT_ROLE_OVERRIDES = [
    'prod': 'prod-jenkins-aws-pipeline-agent',
    'dev': 'dev-jenkins-pipeline-access-role',
]

pipeline {
    agent any

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

    parameters {
        string(name: 'ENV', defaultValue: 'dev', description: 'Name of environment, e.g. dev, qa, prod.')
        string(name: 'SERVICE_NAME', description: 'Name of service, e.g. ows-product, graphql-knowledge')
        string(name: 'CLUSTER_NAME', defaultValue: '', description: 'Name of cluster if different from service. Should not typically be required')
        choice(name: 'AWS_REGION', choices: ['us-east-1', 'us-east-2'], description: 'AWS region name')
        choice(name: 'AWS_ACCOUNT', choices: AWS_ACCOUNT_NAMES, description: 'The AWS account where the service is running')
        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.')
        booleanParam(name: 'REFRESH_PARAMETERS_ONLY', defaultValue: false, description: 'Set this to just refresh the Jenkins job parameters without deploying anything.')
    }

    stages {
        stage('Load Shared Libraries') {
            steps {
                library "jenkins-global-libraries@${params.SHARED_LIBRARIES_VERSION}"
            }
        }
        stage('Validate Parameters') {
            when {
                allOf {
                    not { triggeredBy 'GitHubPushCause' }
                    not { expression { params.REFRESH_PARAMETERS_ONLY } }
                }
            }
            steps {
                script {
                    if (!params.SERVICE_NAME) {
                        error "SERVICE_NAME is required. Please specify the service to redeploy."
                    }
                }
            }
        }
        stage('Redeploy') {
            when {
                allOf {
                    not { triggeredBy 'GitHubPushCause' }
                    not { expression { params.REFRESH_PARAMETERS_ONLY } }
                }
            }
            steps {
                fargateDeploy(
                    environment: params.ENV,
                    awsRegions: [params.AWS_REGION],
                    clusterName: (params.clusterName ?: "${params.ENV}-${params.SERVICE_NAME}"),
                    serviceName: params.SERVICE_NAME,
                    deployMode: 'REDEPLOY',
                    gitCommit: "REDEPLOY_DUMMY_VALUE",
                    awsDeploymentTargetAccountId: AWS_ACCOUNT_IDS_BY_NAME[params.AWS_ACCOUNT],
                    awsDeploymentRoleName: DEPLOYMENT_ROLE_OVERRIDES.get(params.AWS_ACCOUNT, "${params.ENV}-jenkins-pipeline-deploy-role"),
                )
            }
        }
    }

    post {
        cleanup {
            cleanWs()
        }
    }
}

def getAwsAccountsMap() {
    node {
        withAWS(region: 'us-east-1', role: 'shared-jenkins-pipeline-deploy-role', roleAccount: '086679231553', roleSessionName: env.BUILD_TAG, useNode: true) {
            echo "Retrieving available AWS accounts..."
            // This parses json but only returns each list element as a string; so we then need to iterate through each string, parse, and filter it.
            def awsAccountMap = readJSON text: sh(returnStdout: true, script: "aws ssm get-parameters-by-path --path /shared/aws-account-ids/ --query 'Parameters[*].Value' --output json")
            def accountNameIdMap = [:]
            for (accountMapString in awsAccountMap) {
                def account = readJSON text: accountMapString
                accountNameIdMap[account['name']] = account['account_id']
            }
            return accountNameIdMap.sort()
        }
    }
}
