pipeline {
    agent any

    parameters {
        string(name: 'ROLLBACK_TAG', defaultValue: '',
               description: 'Khaali = normal build. Purana build number (jaise 2) = seedha us image par rollback, bina rebuild ke')
    }

    environment {
        REGISTRY   = '51.195.4.170:5000'
        IMAGE_NAME = 'swim/demo-app'
        IMAGE_TAG  = "${params.ROLLBACK_TAG?.trim() ? params.ROLLBACK_TAG : env.BUILD_NUMBER}"
        // Jenkins container ke andar workspace /var/jenkins_home/... hai,
        // par docker daemon HOST par chalta hai jahan wahi folder
        // /opt/devops/data/jenkins/... par hai. -v ke liye HOST ka path chahiye.
        JENKINS_HOME_CONTAINER = '/var/jenkins_home'
        JENKINS_HOME_HOST      = '/opt/devops/data/jenkins'
    }

    options {
        timestamps()
        buildDiscarder(logRotator(numToKeepStr: '20'))
        timeout(time: 20, unit: 'MINUTES')
    }

    stages {
        stage('Checkout') {
            steps {
                checkout scm
                sh 'echo "commit: $(git rev-parse --short HEAD)"'
            }
        }

        stage('Test') {
            when { expression { !params.ROLLBACK_TAG?.trim() } }
            steps {
                sh '''
                    # container ka path -> host ka path badlo
                    HOST_WS=$(echo "$PWD" | sed "s|^${JENKINS_HOME_CONTAINER}|${JENKINS_HOME_HOST}|")
                    echo "container workspace : $PWD"
                    echo "host workspace      : $HOST_WS"

                    docker run --rm -v "$HOST_WS":/src -w /src python:3.12-slim sh -c "
                        pip install --quiet -r requirements-dev.txt &&
                        python -m pytest tests/ -v
                    "
                '''
            }
        }

        stage('Build image') {
            when { expression { !params.ROLLBACK_TAG?.trim() } }
            steps {
                sh '''
                    docker build \
                      --build-arg APP_VERSION=${IMAGE_TAG} \
                      -t ${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG} \
                      -t ${REGISTRY}/${IMAGE_NAME}:latest .
                    docker images ${REGISTRY}/${IMAGE_NAME}
                '''
            }
        }

        stage('Smoke test image') {
            when { expression { !params.ROLLBACK_TAG?.trim() } }
            steps {
                sh '''
                    CID=$(docker run -d -P ${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG})
                    sleep 5
                    docker exec $CID python -c "
import urllib.request, json, sys
r = json.loads(urllib.request.urlopen('http://127.0.0.1:8000/version').read())
print('version endpoint:', r)
assert r['version'] == '${IMAGE_TAG}', 'version galat!'
"
                    docker rm -f $CID
                '''
            }
        }

        stage('Push to registry') {
            when { expression { !params.ROLLBACK_TAG?.trim() } }
            steps {
                withCredentials([usernamePassword(credentialsId: 'registry-creds',
                                                  usernameVariable: 'REG_USER',
                                                  passwordVariable: 'REG_PASS')]) {
                    sh '''
                        echo "$REG_PASS" | docker login ${REGISTRY} -u "$REG_USER" --password-stdin
                        docker push ${REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}
                        docker push ${REGISTRY}/${IMAGE_NAME}:latest
                        docker logout ${REGISTRY}
                    '''
                }
            }
        }

        stage('Deploy to VM') {
            steps {
                withCredentials([usernamePassword(credentialsId: 'registry-creds',
                                                  usernameVariable: 'REG_USER',
                                                  passwordVariable: 'REG_PASS')]) {
                    sh '''
                        export ANSIBLE_HOST_KEY_CHECKING=False
                        export IMAGE_TAG=${IMAGE_TAG}
                        ansible-galaxy collection install community.docker --force -q || true
                        ansible-playbook -i deploy/inventory.ini deploy/deploy.yml
                    '''
                }
            }
        }
    }

    post {
        always {
            sh 'docker image prune -f --filter "until=24h" || true'
            cleanWs()
        }
        success { echo "BUILD ${env.BUILD_NUMBER} SAFAL -> ${env.REGISTRY}/${env.IMAGE_NAME}:${env.IMAGE_TAG}" }
        failure { echo "BUILD ${env.BUILD_NUMBER} FAIL" }
    }
}
