pipeline {
    agent any

    environment {
        APP_NAME        = "Shams"
        IMAGE_NAME      = "shams"
        CONTAINER_NAME  = "shams_app"
        DOCKER_BUILDKIT = '1'
        APP_URL             = "${env.APP_URL}"
        APP_ENV             = "${env.APP_ENV}"
        APP_DEBUG           = "${env.APP_DEBUG}"
        APP_PORT            = "${env.APP_PORT}"
        NETWORK_NAME        = "${env.NETWORK_NAME}"
        MEMORY_LIMIT        = "${env.MEMORY_LIMIT}"
        MEMSWAP_LIMIT       = "${env.MEMSWAP_LIMIT}"
        BUILD_MEMORY        = "${env.BUILD_MEMORY}"
        BUILD_TIMEOUT_MIN   = "${env.BUILD_TIMEOUT_MIN}"
        COMPOSE_FILE        = "${env.COMPOSE_FILE}"
        SLACK_CHANNEL       = "${env.SLACK_CHANNEL}"
        DB_HOST         = "${env.DB_HOST}"
        DB_PORT         = "${env.DB_PORT}"
        DB_DATABASE     = "${env.DB_DATABASE}"
        DB_USERNAME     = "${env.DB_USERNAME}"
        DB_PASSWORD     = credentials('postgres-password')
        REDIS_HOST      = "${env.REDIS_HOST}"
        REDIS_PORT      = "${env.REDIS_PORT}"
        FIREBASE_CREDENTIALS = "${env.FIREBASE_CREDENTIALS}"
        GOOGLE_ROUTE_APIKEY = credentials('shams-google-route-api-key')
        GIT_BRANCH_NAME = "${env.GIT_BRANCH_NAME}"
    }

    stages {

        stage('Notify Build Start') {
            steps {
                script {
                    def commitMsg    = sh(script: 'git log -1 --pretty=%B | head -5', returnStdout: true).trim()
                    def commitHash   = sh(script: 'git log -1 --pretty=%h',           returnStdout: true).trim()
                    def commitAuthor = sh(script: 'git log -1 --pretty=%an',          returnStdout: true).trim()

                    slackSend(
                        channel: env.SLACK_CHANNEL,
                        message: """\
                            |:hammer_and_wrench: *BUILD STARTED* :construction:
                            |> *Job*: `${env.JOB_NAME}` #${env.BUILD_NUMBER}
                            |> *Branch*: `${env.GIT_BRANCH_NAME}`
                            |> *App*: `${env.APP_NAME}`
                            |> *Commit*: `${commitHash}` by *${commitAuthor}*
                            |> *Message*: ${commitMsg}
                            """.stripMargin()
                    )
                }
            }
        }

        stage('Generate .env') {
            steps {
                script {
                    sh 'rm -f .env'
                    withCredentials([
                        string(credentialsId: 'postgres-password',          variable: 'DB_PASSWORD'),
                        string(credentialsId: 'shams-google-route-api-key', variable: 'GOOGLE_ROUTE_APIKEY')
                    ]) {
                        sh '''
cat > .env << EOF
# App
APP_NAME=SHAMS
APP_ENV=''' + APP_ENV + '''
APP_KEY=base64:2npn88yEFFwu4pA6rjwl2/Bfy71fYzZ8jSCkdCOf7Vk=
APP_DEBUG=''' + APP_DEBUG + '''
APP_URL=''' + APP_URL + '''
APP_LOCALE=fr
APP_FALLBACK_LOCALE=fr

# Database
DB_CONNECTION=pgsql
DB_HOST=''' + DB_HOST + '''
DB_PORT=''' + DB_PORT + '''
DB_DATABASE=''' + DB_DATABASE + '''
DB_USERNAME=''' + DB_USERNAME + '''
DB_PASSWORD=${DB_PASSWORD}

# Cache / Queue / Session
SESSION_DRIVER=database
CACHE_STORE=database
QUEUE_CONNECTION=database

# Redis
REDIS_CLIENT=predis
REDIS_HOST=''' + REDIS_HOST + '''
REDIS_PORT=''' + REDIS_PORT + '''

# Firebase
FIREBASE_CREDENTIALS=''' + FIREBASE_CREDENTIALS + '''

# Google
GOOGLE_ROUTE_APIKEY=${GOOGLE_ROUTE_APIKEY}

# Media
QUEUE_CONVERSIONS_BY_DEFAULT=false
EOF
                '''
                    }
                }
            }
        }

        stage('Run Docker Compose') {
            steps {
                script {
                    sh "docker compose -f ${COMPOSE_FILE} down"
                    sh """
                        APP_PORT=${APP_PORT} \
                        NETWORK_NAME=${NETWORK_NAME} \
                        MEMORY_LIMIT=${MEMORY_LIMIT} \
                        MEMSWAP_LIMIT=${MEMSWAP_LIMIT} \
                        APP_ENV=${APP_ENV} \
                        docker compose -f ${COMPOSE_FILE} up --build -d
                    """
                }
            }
        }

        stage('Run Migrations') {
            steps {
                sh 'docker exec -u 0 shams_app php artisan migrate --force'
            }
        }

    }

    post {
        success {
            slackSend(
                channel: env.SLACK_CHANNEL,
                message: """\
                    |:rocket: *DEPLOYMENT SUCCESS*
                    |> *Job*: `${env.JOB_NAME}` #${env.BUILD_NUMBER}
                    |> *App*: `${env.APP_NAME}`
                    |> *URL*: <${env.APP_URL}|Open App>
                    |> *Time*: ${currentBuild.durationString}
                    """.stripMargin()
            )
        }
        failure {
            slackSend(
                channel: env.SLACK_CHANNEL,
                message: """\
                    |:skull: *BUILD FAILED*
                    |> *Job*: `${env.JOB_NAME}` #${env.BUILD_NUMBER}
                    |> *App*: `${env.APP_NAME}`
                    |> *Error*: <${env.BUILD_URL}|View Logs>
                    |> *Time*: ${currentBuild.durationString}
                    """.stripMargin()
            )
        }
        aborted {
            slackSend(
                channel: env.SLACK_CHANNEL,
                message: """\
                    |:warning: *BUILD ABORTED*
                    |> *Job*: `${env.JOB_NAME}` #${env.BUILD_NUMBER}
                    |> *App*: `${env.APP_NAME}`
                    |> *Time*: ${currentBuild.durationString}
                    """.stripMargin()
            )
        }
        always {
            cleanWs()
        }
    }
}
