// ============================================================
// juwan-backend CD Pipeline — Harbor Webhook 模式
// 适用场景：生产环境，Harbor 推送镜像后主动通知 Jenkins
//
// 工作原理：
//   1. Harbor 配置 Webhook，推送事件发送 POST 到 Jenkins
//   2. Jenkins Generic Webhook Trigger 插件解析 payload
//   3. 提取镜像名称，触发对应 Deployment 的滚动更新
//
// 前置条件（见 docs/jenkins-cd/02-production-webhook-setup.md）：
//   - Jenkins 插件：Generic Webhook Trigger
//   - Jenkins 凭据：kubeconfig-prod（Secret file，生产 kubeconfig）
//   - Harbor Webhook 配置指向本 Jenkins URL
// ============================================================

pipeline {
    agent any

    // ── Generic Webhook Trigger 插件配置 ─────────────────────
    // Harbor push 事件 payload 结构：
    // {
    //   "type": "PUSH_ARTIFACT",
    //   "event_data": {
    //     "resources": [{
    //       "resource_url": "harbor.example.com/juwan/user-api:abc1234"
    //     }],
    //     "repository": { "name": "user-api" }
    //   }
    // }
    triggers {
        GenericTrigger(
            genericVariables: [
                // 提取镜像仓库名（即服务名，如 user-api）
                [key: 'REPO_NAME',     value: '$.event_data.repository.name'],
                // 提取完整镜像 URL（含 tag）
                [key: 'RESOURCE_URL',  value: '$.event_data.resources[0].resource_url'],
                // 提取事件类型（只处理 PUSH_ARTIFACT）
                [key: 'EVENT_TYPE',    value: '$.type']
            ],
            // Webhook token，在 Harbor 配置 Webhook URL 时附加：
            // http://jenkins.example.com/generic-webhook-trigger/invoke?token=JUWAN_CD_TOKEN
            token: 'JUWAN_CD_TOKEN',
            // 只处理推送事件
            regexpFilterText:    '$EVENT_TYPE',
            regexpFilterExpression: 'PUSH_ARTIFACT',
            causeString: 'Harbor push: $REPO_NAME ($RESOURCE_URL)',
            printContributedVariables: true,
            printPostContent: true
        )
    }

    parameters {
        string(
            name: 'HARBOR_REGISTRY',
            defaultValue: 'harbor.example.com',
            description: 'Harbor 镜像仓库地址'
        )
        string(
            name: 'HARBOR_PROJECT',
            defaultValue: 'juwan',
            description: 'Harbor 项目名'
        )
        string(
            name: 'K8S_NAMESPACE',
            defaultValue: 'juwan',
            description: 'Kubernetes 命名空间'
        )
        string(
            name: 'KUBECONFIG_CREDENTIAL',
            defaultValue: 'kubeconfig-prod',
            description: 'Jenkins 中存储生产 kubeconfig 的凭据 ID'
        )
    }

    environment {
        KUBECTL = 'kubectl'
    }

    stages {

        stage('Validate Trigger') {
            steps {
                script {
                    echo "=== Harbor Webhook 触发 ==="
                    echo "事件类型: ${env.EVENT_TYPE}"
                    echo "仓库名称: ${env.REPO_NAME}"
                    echo "镜像 URL: ${env.RESOURCE_URL}"

                    if (!env.REPO_NAME?.trim()) {
                        error("Webhook payload 中未找到 repository.name，请检查 Harbor Webhook 配置")
                    }
                }
            }
        }

        stage('Deploy') {
            steps {
                script {
                    def svc = env.REPO_NAME.trim()

                    withCredentials([
                        file(credentialsId: params.KUBECONFIG_CREDENTIAL, variable: 'KUBECONFIG_FILE')
                    ]) {
                        // 验证 Deployment 存在
                        def exists = sh(
                            script: """
                                KUBECONFIG=\${KUBECONFIG_FILE} ${KUBECTL} get deployment ${svc} \\
                                    -n ${params.K8S_NAMESPACE} \\
                                    --ignore-not-found \\
                                    -o name 2>/dev/null || echo ""
                            """,
                            returnStdout: true
                        ).trim()

                        if (!exists) {
                            error("Deployment ${svc} 不存在于命名空间 ${params.K8S_NAMESPACE}")
                        }

                        echo "触发滚动更新: ${svc}"

                        // 用 image tag 中的 digest/sha 更新镜像，确保精确版本
                        // resource_url 格式: harbor.example.com/juwan/user-api:abc1234
                        def imageRef = env.RESOURCE_URL.trim()

                        sh """
                            KUBECONFIG=\${KUBECONFIG_FILE} ${KUBECTL} set image deployment/${svc} \\
                                ${svc}=${imageRef} \\
                                -n ${params.K8S_NAMESPACE}
                        """

                        def rolloutStatus = sh(
                            script: """
                                KUBECONFIG=\${KUBECONFIG_FILE} ${KUBECTL} rollout status deployment/${svc} \\
                                    -n ${params.K8S_NAMESPACE} \\
                                    --timeout=300s
                            """,
                            returnStatus: true
                        )

                        if (rolloutStatus == 0) {
                            echo "✅ ${svc} 部署成功 → ${imageRef}"
                        } else {
                            echo "❌ ${svc} 部署失败，执行回滚..."
                            sh """
                                KUBECONFIG=\${KUBECONFIG_FILE} ${KUBECTL} rollout undo deployment/${svc} \\
                                    -n ${params.K8S_NAMESPACE}
                            """
                            error("${svc} 部署失败，已回滚")
                        }
                    }
                }
            }
        }
    }

    post {
        success {
            echo "✅ ${env.REPO_NAME} 部署完成"
        }
        failure {
            echo "❌ ${env.REPO_NAME} 部署失败，请检查日志"
        }
    }
}
