// Pipeline script for: https://scheduler.theorchard.io/job/ows-dmp-scheduler/

import java.time.LocalDate
import java.time.DayOfWeek

String GITHUB_REPOSITORY = 'ows-dmp'
List<String> AWS_REGIONS = ['us-east-1']
String SLACK_ALERTS_CHANNEL = '#fansifter-alerts'
String SLACK_BUILDS_CHANNEL = '#fansifter-builds'
String QA_ACCOUNT_ID = '437795906767'
String QA_DEPLOYMENT_ROLE = 'qa-ows-dmp-scheduler-role'
String QA_SESSION_NAME = 'qa-ows-dmp-scheduler-session'
String PROD_ACCOUNT_ID = '437795906767'
String PROD_DEPLOYMENT_ROLE = 'prod-ows-dmp-scheduler-role'
String PROD_SESSION_NAME = 'prod-ows-dmp-scheduler-session'


def cronSchedule = 'H 0 * * *'

def isCronTrigger() {
    try {
        def buildCauses = currentBuild.getBuildCauses()
        for (buildCause in buildCauses) {
            if (buildCause != null) {
                if (buildCause.shortDescription.contains("Started by timer")) {
                    return true
                }
            }
        }
        return false
    } catch(theError) {
        echo "ERROR: Exception in isCronTrigger(): ${theError}"
        return false
    }
}

def IsGeoNamesCronTrigger() {
    def today = LocalDate.now()
    return today.getDayOfWeek() == DayOfWeek.MONDAY && isCronTrigger()
}

def syncFivetranTablesState(Map args = [:]) {
    def syncRole = args.syncRole
    def accountId = args.accountId
    def sessionName = args.sessionName
    def region = args.region
    def environment = args.environment

    try {
        echo "Starting Fivetran tables state sync for environment: ${environment}"
        withEnv(["ENVIRONMENT=${environment}",]) {
            withAWS(role: syncRole, roleAccount: accountId, roleSessionName: sessionName, region: region, useNode: true) {
                timeout(time: 30, unit: 'MINUTES') {
                    sh "make sync_fivetran_tables_state"
                }
            }
        }
        echo "Successfully completed Fivetran tables state sync for environment: ${environment}"
    } catch (Exception e) {
        echo "ERROR: Failed to sync Fivetran tables state for environment: ${environment}"
        echo "Error details: ${e.getMessage()}"
        throw e
    }
}

def syncGeonamesData(Map args = [:]) {
    def syncRole = args.syncRole
    def accountId = args.accountId
    def sessionName = args.sessionName
    def region = args.region
    def environment = args.environment

    withEnv(["ENVIRONMENT=${environment}",]) {
        withAWS(role: syncRole, roleAccount: accountId, roleSessionName: sessionName, region: region, useNode: true) {
            sh "make sync_geonames_data"
        }
    }
}


pipeline {
    agent any

    triggers {
        cron(cronSchedule)
    }

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

    parameters {
        booleanParam(name: 'SYNC_FIVETRAN_ON_QA', defaultValue: true, description: 'Whether or not to sync Fivetran on qa.')
        booleanParam(name: 'SYNC_FIVETRAN_ON_PROD', defaultValue: false, description: 'Whether or not to sync Fivetran on prod.')
        booleanParam(name: 'SYNC_GEONAMES_ON_QA', defaultValue: true, description: 'Whether or not to sync GeoNames on qa.')
        booleanParam(name: 'SYNC_GEONAMES_ON_PROD', defaultValue: false, description: 'Whether or not to sync GeoNames on 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.')
    }

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

        stage('Sync Fivetran tables state QA') {
            when {
                allOf {
                    expression { return params.SYNC_FIVETRAN_ON_QA || isCronTrigger() }
                }
            }
            steps {
                script {
                    try {
                        syncFivetranTablesState(
                            syncRole: QA_DEPLOYMENT_ROLE,
                            accountId: QA_ACCOUNT_ID,
                            sessionName: QA_SESSION_NAME,
                            region: AWS_REGIONS[0],
                            environment: 'qa',
                        )
                    } catch (Exception e) {
                        echo "STAGE ERROR: Sync Fivetran tables state QA failed"
                        echo "Stage error details: ${e.getMessage()}"
                        currentBuild.result = 'FAILURE'
                        throw e
                    }
                }
            }
        }
        stage('Sync Geonames data QA') {
            when {
                allOf {
                    expression { return params.SYNC_GEONAMES_ON_QA || IsGeoNamesCronTrigger() }
                }
            }
            steps {
                syncGeonamesData(
                    syncRole: QA_DEPLOYMENT_ROLE,
                    accountId: QA_ACCOUNT_ID,
                    sessionName: QA_SESSION_NAME,
                    region: AWS_REGIONS[0],
                    environment: 'qa',
                )
            }
        }

        stage('Sync Fivetran tables state PROD') {
            when {
                allOf {
                    expression { 
                        return params.SYNC_FIVETRAN_ON_PROD || 
                               ((currentBuild.result == null || currentBuild.result == 'SUCCESS') && isCronTrigger())
                    }
                }
            }
            steps {
                script {
                    try {
                        syncFivetranTablesState(
                            syncRole: PROD_DEPLOYMENT_ROLE,
                            accountId: PROD_ACCOUNT_ID,
                            sessionName: PROD_SESSION_NAME,
                            region: AWS_REGIONS[0],
                            environment: 'prod',
                        )
                    } catch (Exception e) {
                        echo "STAGE ERROR: Sync Fivetran tables state PROD failed"
                        echo "Stage error details: ${e.getMessage()}"
                        currentBuild.result = 'FAILURE'
                        throw e
                    }
                }
            }
        }
        stage('Sync Geonames data PROD') {
            when {
                allOf {
                    expression { return params.SYNC_GEONAMES_ON_PROD || IsGeoNamesCronTrigger() }
                }
            }
            steps {
                syncGeonamesData(
                    syncRole: PROD_DEPLOYMENT_ROLE,
                    accountId: PROD_ACCOUNT_ID,
                    sessionName: PROD_SESSION_NAME,
                    region: AWS_REGIONS[0],
                    environment: 'prod',
                )
            }
        }
    }

    post {
        always {
            script {
                slackNotify channel: SLACK_BUILDS_CHANNEL
            }
        }
        failure {
            script {
                slackNotify channel: SLACK_ALERTS_CHANNEL
            }
        }
        fixed {
            script {
                slackNotify channel: SLACK_ALERTS_CHANNEL
            }
        }
        cleanup {
            cleanWs()
        }
    }
}
