@Library('pipeline-utils')

import com.snowflake.DevEnvUtils

String prodServerUrl = 'ci-prod-200'
String devServerUrl = 'sql-001'
String prodArtifactoryRepo = 'internal-production-docker-data_migration-local'
String devArtifactoryRepo = 'internal-development-docker-data_migration-local'
Boolean isProdServer
Boolean isDevServer
String artifactoryRepo
String imageName = 'data-migration-orchestrator'
String version
String imageTagAmd64
String imageTagArm64

pipeline {
    agent {
        label 'small-node-snowos'
    }
    options {
        skipDefaultCheckout()
    }
    stages {
        stage("Detect Environment") {
            steps {
                script {
                    isProdServer = env.JENKINS_URL?.contains(prodServerUrl) ?: false
                    isDevServer = env.JENKINS_URL?.contains(devServerUrl) ?: false

                    if (isProdServer) {
                        echo "Running on PRODUCTION server: ${env.JENKINS_URL}"
                        artifactoryRepo = prodArtifactoryRepo
                    } else if (isDevServer) {
                        echo "Running on DEV server: ${env.JENKINS_URL}"
                        artifactoryRepo = devArtifactoryRepo
                    } else {
                        error("Unknown server: ${env.JENKINS_URL}. Expected ${prodServerUrl} or ${devServerUrl}")
                    }

                    echo "Using Artifactory repository: ${artifactoryRepo}"
                }
            }
        }

        stage("Checkout") {
            steps {
                script {
                    checkout([
                        $class: 'GitSCM',
                        branches: scm.branches,
                        extensions: [],
                        userRemoteConfigs: [[
                            url: scm.userRemoteConfigs[0].url,
                            credentialsId: 'jenkins-snowflake-github-app-2-emu'
                        ]]
                    ])
                }
            }
        }

        stage("Set Environment") {
            steps {
                script {
                    echo "Extracting version from __version__.py..."
                    version = sh(
                        script: "grep -oP '__version__\\s*=\\s*\"\\K[^\"]+' __version__.py",
                        returnStdout: true
                    ).trim()

                    // Set image tags
                    imageTagAmd64 = "${imageName}:${version}"
                    imageTagArm64 = "${imageName}-arm64:${version}"

                    echo "Environment validation passed."
                    echo "Version from __version__.py: ${version}"
                    echo "Image tag (AMD64): ${imageTagAmd64}"
                    echo "Image tag (ARM64): ${imageTagArm64}"
                }
            }
        }

        stage("Build Docker Images") {
            steps {
                script {
                    sh """
                        echo "=== Setting up Docker Buildx for multi-platform builds ==="
                        # Install QEMU emulation for ARM64 builds
                        docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

                        # Create and use a new buildx builder instance for multi-platform support
                        docker buildx create --name multiplatform-builder --use --bootstrap

                        echo "=== Building Docker Image (AMD64) ==="
                        docker buildx build --platform linux/amd64 --load \
                            -t "${imageTagAmd64}" \
                            -f "data-migration-orchestrator/Dockerfile" \
                            .
                        echo "=== Docker Build Complete (AMD64) ==="

                        echo "=== Building Docker Image (ARM64) ==="
                        docker buildx build --platform linux/arm64 --load \
                            -t "${imageTagArm64}" \
                            -f "data-migration-orchestrator/Dockerfile" \
                            .
                        echo "=== Docker Build Complete (ARM64) ==="
                    """
                }
            }
        }

        stage("Validate Local Images") {
            steps {
                script {
                    // Function to check if image exists locally
                    def checkLocalImageExists = { imageTag ->
                        return sh(
                            script: "docker images --format '{{.Repository}}:{{.Tag}}' | grep -q '^${imageTag}\$'",
                            returnStatus: true
                        )
                    }

                    echo "Validating Docker images exist..."
                    def imageExistsAmd64 = checkLocalImageExists(imageTagAmd64)
                    def imageExistsArm64 = checkLocalImageExists(imageTagArm64)

                    if (imageExistsAmd64 != 0) {
                        error("Docker image '${imageTagAmd64}' not found. Please ensure the image was built and tagged correctly.")
                    }

                    if (imageExistsArm64 != 0) {
                        error("Docker image '${imageTagArm64}' not found. Please ensure the ARM64 image was built and tagged correctly.")
                    }

                    echo "All images validated successfully. Available Docker images:"
                    sh "docker images | grep ${imageName}"
                }
            }
        }

        stage("Check Artifactory Repository") {
            steps {
                script {
                    new DevEnvUtils().withSfCli {
                        echo "Authenticating with OCI registry..."
                        sh "sf artifact oci auth"
                        echo "Authentication complete."

                        // Function to check if image exists in remote repository
                        def checkRemoteImageExists = { imagePath ->
                            return sh(
                                script: """
                                    sf artifact container-images exists \\
                                        --repository ${artifactoryRepo} \\
                                        --name ${imagePath} \\
                                        --tag ${version}
                                """,
                                returnStatus: true
                            )
                        }

                        echo "Checking if AMD64 image already exists in remote repository..."
                        def remoteImageExistsAmd64 = checkRemoteImageExists(imageName)

                        if (remoteImageExistsAmd64 == 0) {
                            error("Image '${imageName}:${version}' already exists in repository '${artifactoryRepo}'. Cannot push duplicate version.")
                        }

                        echo "Checking if ARM64 image already exists in remote repository..."
                        def remoteImageExistsArm64 = checkRemoteImageExists("${imageName}-arm64")

                        if (remoteImageExistsArm64 == 0) {
                            error("Image '${imageName}-arm64:${version}' already exists in repository '${artifactoryRepo}'. Cannot push duplicate version.")
                        }

                        echo "All images validated - none exist in remote repository. Ready to push."
                    }
                }
            }
        }

        stage("Push AMD64 Image to Artifactory") {
            steps {
                script {
                    new DevEnvUtils().withSfCli {
                        echo "Pushing AMD64 image to repository: ${artifactoryRepo}"

                        sh """
                            sf artifact container-images push \\
                                --image ${imageTagAmd64} \\
                                --name ${imageName} \\
                                --repository ${artifactoryRepo} \\
                                --tag ${version}
                        """
                        echo "AMD64 image push complete."
                    }
                }
            }
        }

        stage("Push ARM64 Image to Artifactory") {
            steps {
                script {
                    new DevEnvUtils().withSfCli {
                        echo "Pushing ARM64 image to repository: ${artifactoryRepo}"

                        sh """
                            sf artifact container-images push \\
                                --image ${imageTagArm64} \\
                                --name ${imageName}-arm64 \\
                                --repository ${artifactoryRepo} \\
                                --tag ${version}
                        """
                        echo "ARM64 image push complete."

                        echo "All images pushed successfully to Artifactory!"
                    }
                }
            }
        }
    }
    post {
        always {
            script {
                // Clean up the buildx builder
                sh """
                    echo "=== Cleaning up Docker Buildx ==="
                    docker buildx rm multiplatform-builder || true
                    echo "=== Buildx cleanup complete ==="
                """
            }
            cleanWs()
        }
    }
}
