pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
spec:
  initContainers:
  - name: install-uv
    image: icr.io/taas-jenkins-public/jonk/agent-jnlp:latest
    command: ['sh', '-c']
    args:
      - |
        set -eux
        curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR=/opt/uv/bin sh
    volumeMounts:
    - name: uv-bin
      mountPath: /opt/uv/bin
  containers:
  - name: jnlp
    env:
    - name: JENKINS_JAVA_OPTS
      value: -Xmx512m -XX:+UnlockExperimentalVMOptions -XX:+UseContainerSupport -Dorg.jenkinsci.plugins.gitclient.Git.timeOut=60
    - name: PATH
      value: /opt/uv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    image: icr.io/taas-jenkins-public/jonk/agent-jnlp:latest
    imagePullPolicy: Always
    resources:
      requests:
        memory: "1Gi"
        cpu: "250m"
      limits:
        memory: "4Gi"
        cpu: "2"
    volumeMounts:
    - name: dev-shm
      mountPath: /dev/shm
    - name: uv-bin
      mountPath: /opt/uv/bin
  volumes:
  - name: dev-shm
    emptyDir:
      medium: Memory
      sizeLimit: 256Mi
  - name: uv-bin
    emptyDir: {}
'''
        }
    }
    parameters {
        string(
            name: 'BRANCH',
            defaultValue: 'main',
            description: 'Git branch to checkout from the repository'
        )
        string(
            name: 'PYPI_VERSION',
            defaultValue: '',
            description: 'Version number to publish to PyPI (e.g., 1.0.0)'
        )
        choice(
            name: 'PYPI_INSTANCE',
            choices: ['test', 'production'],
            description: 'PyPI instance to publish to (test or production)'
        )
    }
    environment {
        MCP_VERSION_FILE = 'src/di_mcp/__version__.py'
        UV_LINK_MODE = 'copy'
    }
    stages {
        stage('Check Parameters') {
            steps {
                script {
                    if (!env.PYPI_VERSION?.trim()) {
                        error "No version provided via the PYPI_VERSION environment variable."
                    }

                    withCredentials([
                        string(credentialsId: 'pypi-test-token', variable: 'PYPI_TOKEN_TEST'),
                        string(credentialsId: 'pypi-prod-token', variable: 'PYPI_TOKEN_PROD')
                    ]) {
                        if (env.PYPI_INSTANCE == 'production') {
                            env.TWINE_USERNAME = '__token__'
                            env.TWINE_PASSWORD = PYPI_TOKEN_PROD  // pragma: allowlist secret
                        } else if (env.PYPI_INSTANCE == 'test') {
                            env.TWINE_REPOSITORY_URL = 'https://test.pypi.org/legacy/'
                            env.TWINE_USERNAME = '__token__'
                            env.TWINE_PASSWORD = PYPI_TOKEN_TEST  // pragma: allowlist secret
                        } else {
                            error "Invalid or empty value for PYPI_INSTANCE. Valid options are: {production, test}."
                        }
                    }
                }
            }
        }
        stage('Checkout watsonx.data integration MCP from GitHub') {
            steps {
                dir('mcp') {
                    git(
                        url: 'git@github.ibm.com:watsonx-data-integration/di-mcp.git',
                        credentialsId: 'github-test-private-key',
                        branch: "${params.BRANCH}"
                    )
                }
            }
        }
        stage('Update Version') {
            steps {
                dir('mcp') {
                    sh '''
                        echo "Updating version number to: ${PYPI_VERSION}"
                        sed -i.old "s/\\".*\\"/\\"${PYPI_VERSION}\\"/" ${MCP_VERSION_FILE}
                        rm ${MCP_VERSION_FILE}.old
                    '''
                }
            }
        }
        stage('Build') {
            steps {
                dir('mcp') {
                    sh 'uv build'
                }
            }
        }
        stage('Sign and Verify Artifacts') {
            steps {
                withCredentials([
                    string(credentialsId: 'code_signing_password', variable: 'CODE_SIGNING_P12_PASSWORD'),
                    string(credentialsId: 'code_signing_pfx', variable: 'pfx_file'),
                ]) {
                    script {
                        def codeSigningPfxFile = '/tmp/code_signing.pfx'

                        sh "echo '${pfx_file}' | base64 -d > ${codeSigningPfxFile}"

                        // https://github.ibm.com/TAAS/Jenkins-on-Kubernetes/blob/main/doc/reference/jenkins-agent-image.md#about-garasign
                        def garasignOutput = withEnv([
                            "CODE_SIGNING_PFX_FILE=${codeSigningPfxFile}",
                        ]) {
                            sh(script: '''
                                set -e

                                # Setup garasign client and capture output
                                echo "=== Setting up Garasign client ==="
                                setup-garasign-client

                                echo "=== Extracting key alias ==="
                                KEY_ALIAS=$(/opt/Garantir/bin/garasign listkeys | awk '/Found key:/ {print $NF; exit}')
                                echo "Found key alias: ${KEY_ALIAS}"

                                echo "=== Exporting public key ==="
                                /opt/Garantir/bin/garasign export --key "${KEY_ALIAS}" --outputDirectory /tmp/public-keys

                                echo "=== Getting COSIGN_KEY URI ==="
                                COSIGN_KEY=$(cosign pkcs11-tool list-keys-uris --module-path /usr/local/lib/Garantir/GRS/libgrsp11.so --slot-id 1 | awk '/URI:/ {print $NF; exit}')

                                # Output values for Jenkins to capture
                                echo "KEY_ALIAS=${KEY_ALIAS}"
                                echo "COSIGN_CERT_CHAIN=/tmp/public-keys/${KEY_ALIAS}.pem.chain"
                                echo "COSIGN_KEY=${COSIGN_KEY}"
                            ''', returnStdout: true)
                        }

                        // Parse the output and set environment variables
                        garasignOutput.split('\n').each { line ->
                            if (line.startsWith('KEY_ALIAS=')) {
                                env.KEY_ALIAS = line.substring('KEY_ALIAS='.length())
                            } else if (line.startsWith('COSIGN_CERT_CHAIN=')) {
                                env.COSIGN_CERT_CHAIN = line.substring('COSIGN_CERT_CHAIN='.length())
                            } else if (line.startsWith('COSIGN_KEY=')) {
                                env.COSIGN_KEY = line.substring('COSIGN_KEY='.length())
                            }
                        }

                        echo "✓ Garasign setup complete. Key: ${env.KEY_ALIAS}"
                    }

                    dir('mcp') {
                        withEnv([
                            "COSIGN_KEY=${env.COSIGN_KEY}",
                            "CODE_SIGNING_P12_PASSWORD=${env.CODE_SIGNING_P12_PASSWORD}"
                        ]) {
                            sh '''
                                echo "=== Creating attestations directory ==="
                                mkdir -p attestations

                                echo "=== Signing distribution files with cosign ==="

                                for file in dist/*.whl dist/*.tar.gz; do
                                    if [ -f "$file" ]; then
                                        filename=$(basename "$file")

                                        echo "Signing: $filename"
                                        cosign sign-blob --yes \
                                            --key "${COSIGN_KEY}" \
                                            --tlog-upload=false \
                                            --output-signature "attestations/${filename}.sig" \
                                            --output-certificate "attestations/${filename}.crt" \
                                            "$file"

                                        # Verify files were created
                                        echo "Checking generated signature and certificate:"
                                        ls -l "attestations/${filename}.sig" "attestations/${filename}.crt"
                                        echo "✓ Signed: $filename"
                                    fi
                                done

                                echo "=== Code signing complete ==="
                                ls -lh dist/
                                echo "=== Attestations created ==="
                                ls -lh attestations/

                                echo "=== Verifying signed artifacts ==="

                                failed=0

                                for file in dist/*.whl dist/*.tar.gz; do
                                    if [ -f "$file" ]; then
                                        filename=$(basename "$file")

                                        echo "Verifying file: $file"
                                        echo "Using signature: attestations/${filename}.sig"

                                        if ! cosign verify-blob \
                                            --key "${COSIGN_KEY}" \
                                            --signature "attestations/${filename}.sig" \
                                            --insecure-ignore-tlog \
                                            "$file"; then
                                            echo "✗ Verification failed for $filename"
                                            failed=1
                                        else
                                            echo "✓ Verification successful for $filename"
                                        fi
                                    fi
                                done

                                if [ $failed -eq 1 ]; then
                                    echo "=== Verification failed for one or more artifacts ==="
                                    exit 1
                                fi

                                echo "=== All artifacts verified successfully ==="
                            '''
                        }
                    }
                }
            }
        }
        stage('Archive Artifacts') {
            steps {
                dir('mcp') {
                    archiveArtifacts artifacts: 'dist/*.whl, dist/*.tar.gz, attestations/*.sig, attestations/*.crt', fingerprint: true
                }
            }
        }
        stage('Upload') {
            steps {
                dir('mcp') {
                    sh 'uv run twine upload --non-interactive dist/*.whl dist/*.tar.gz'
                }
            }
        }
    }
    post {
        always {
            cleanWs()
        }
    }
}
