import groovy.json.JsonOutput

AWS_REGION = "us-west-2"

DEPLOY_BRANCHES = ["develop"]
DEPLOY_BRANCHES_WITH_CONFIRMATION = ["master"]
SLACK_CHANNEL = "#e2-mdaas-deploys"

DEPLOY_CONFIRMATION_ENABLED = DEPLOY_BRANCHES_WITH_CONFIRMATION.contains(env.BRANCH_NAME)
DEPLOY_ENABLED = DEPLOY_BRANCHES.contains(env.BRANCH_NAME) || DEPLOY_CONFIRMATION_ENABLED
DEPLOY_NAME = env.BRANCH_NAME == "master" ? "Production" : "Staging"
DEPLOY_TARGET = env.BRANCH_NAME == "master" ? "prod" : "staging"
AWS_CREDENTIALS_DEV = "twitch-mdaas-ingest-dev"
AWS_CREDENTIALS_PROD = "twitch-mdaas-ingest-prod"
AWS_CREDENTIALS = DEPLOY_TARGET == "prod" ? AWS_CREDENTIALS_PROD : AWS_CREDENTIALS_DEV

JOB_URL = "${env.JENKINS_URL}job/${env.JOB_NAME.replace("/", "/job/")}/"

def gitCommitSha() {
    return sh(script: "git log -1 --format=%h", returnStdout: true).trim()
}

def gitCommitMessage() {
    return sh(script: "git log -1 --format=%B", returnStdout: true).trim()
}

def commitLink() {
    sha = gitCommitSha()
    msg = gitCommitMessage()
    return "<https://git.xarth.tv/devhub/mdaas-ingest/commit/${sha}|${sha}> ${msg}"
}

def message(payload) {
    // TODO
}

def startedMessage(stageName, icon) {
    message([[
        title: "Ingest Service: [${env.BRANCH_NAME}] ${DEPLOY_NAME} ${stageName} started ${icon}",
        text: commitLink(),
    ]])
}

def successMessage(stageName) {
    message([[
        title: "Ingest Service: [${env.BRANCH_NAME}] ${DEPLOY_NAME} ${stageName} succeeded 🎉",
        color: "good",
        text: commitLink(),
    ]])
}

def failureMessage(stageName) {
    message([[
        title: "Ingest Service: [${env.BRANCH_NAME}] ${DEPLOY_NAME} ${stageName} failed 💀",
        color: "danger",
        text: commitLink(),
        actions: [[
            type: "button",
            text: "Logs",
            url: "${env.BUILD_URL}console"
        ]]
    ]])
}

def confirmDeployMessage() {
    message([[
        title: "Ingest Service: [${env.BRANCH_NAME}] ${DEPLOY_NAME} canary deployment succeeded 🎉",
        color: "good",
        text: commitLink(),
        actions: [[
            type: "button",
            text: "Deploy to All",
            url: "${JOB_URL}"
        ]]
    ]])
}

def confirmCanaryDeployMessage() {
    message([[
        title: "Ingest Service: [${env.BRANCH_NAME}] ${DEPLOY_NAME} build succeeded 🎉",
        color: "good",
        text: commitLink(),
        actions: [[
            type: "button",
            text: "Deploy Canary",
            url: "${JOB_URL}"
        ]]
    ]])
}

pipeline {
    agent any

    options {
        disableConcurrentBuilds()
        timeout(time: 1, unit: "HOURS")
        timestamps()
    }

    environment {
        FORCE_DEPLOYS = "true"
        E2E_TEST_USER_CLIENT_SECRET = credentials("e2e-test-user-client-secret")
    }

    stages {
        stage("Build") {
            steps {
                script {
                    if (DEPLOY_ENABLED) {
                        startedMessage("build", "🔨")
                    }
                }

                sh "make build-docker"
            }

            post {
                success {
                    script {
                        if (DEPLOY_ENABLED) {
                            successMessage("build")
                        }
                    }
                }

                failure {
                    script {
                        if (DEPLOY_ENABLED) {
                            failureMessage("build")
                        }
                    }
                }
            }
        }

        stage("Test & Lint") {
            parallel {
                stage("Lint") {
                    steps {
                        script {
                            if (DEPLOY_ENABLED) {
                                startedMessage("lint", "🔨")
                            }
                        }

                        sh "make lint-docker"
                    }

                    post {
                        success {
                            script {
                                if (DEPLOY_ENABLED) {
                                    successMessage("lint")
                                }
                            }
                        }

                        failure {
                            script {
                                if (DEPLOY_ENABLED) {
                                    failureMessage("lint")
                                }
                            }
                        }
                    }
                }

                stage("Test") {
                    steps {
                        script {
                            if (DEPLOY_ENABLED) {
                                startedMessage("tests", "🔨")
                            }
                        }

                        sh "make test-docker"
                    }

                    post {
                        success {
                            script {
                                if (DEPLOY_ENABLED) {
                                    successMessage("tests")
                                }
                            }
                        }

                        failure {
                            script {
                                if (DEPLOY_ENABLED) {
                                    failureMessage("tests")
                                }
                            }
                        }
                    }
                }
            }
        }

        stage("E2E Test") {
            steps {
                script {
                    if (DEPLOY_ENABLED) {
                        startedMessage("E2E tests", "🔨")
                    }
                }

                // running e2e tests always uses dev credentials 
                withAWS(credentials: AWS_CREDENTIALS_DEV, region: AWS_REGION) {
                    sh "make e2e-test"
                }
            }

            post {
                success {
                    script {
                        if (DEPLOY_ENABLED) {
                            successMessage("E2E tests")
                        }
                    }
                }

                failure {
                    script {
                        if (DEPLOY_ENABLED) {
                            failureMessage("E2E tests")
                        }
                    }
                }
            }
        }

        stage("Confirm canary deploy") {
            when {
                expression { return DEPLOY_CONFIRMATION_ENABLED }
            }

            options {
                timeout(time: 5, unit: "MINUTES")
            }

            steps {
                script { confirmCanaryDeployMessage() }
                input message: "Deploy to ${DEPLOY_TARGET}?"
                echo "Deploying to ${DEPLOY_TARGET}."
            }
        }

        stage("Deploy to canary") {
            when {
                expression { return DEPLOY_ENABLED }
            }

            steps {
                script { startedMessage("canary deploy", "🚀") }

                withAWS(credentials: AWS_CREDENTIALS, region: AWS_REGION) {
                    sh "make deploy-canary"
                }
            }

            post {
                success { script { successMessage("canary deploy") } }
                failure { script { failureMessage("canary deploy") } }
            }
        }

        stage("Confirm deploy") {
             when {
                 expression { return DEPLOY_CONFIRMATION_ENABLED }
             }

             options {
                 timeout(time: 30, unit: "MINUTES")
             }

             steps {
                 script { confirmDeployMessage() }
                 input message: "Deploy to ${DEPLOY_TARGET}?"
                 echo "Deploying to ${DEPLOY_TARGET}."
             }
         }

        stage("Deploy") {
            when {
                expression { return DEPLOY_ENABLED }
            }

            steps {
                script { startedMessage("deploy", "🚀") }

                withAWS(credentials: AWS_CREDENTIALS, region: AWS_REGION) {
                    sh "make deploy"
                }
            }

            post {
                success { script { successMessage("deploy") } }
                failure { script { failureMessage("deploy") } }
            }
        }
    }
}
