// live.fuhua91.com 部署流水线（基于 Jenkinsfile2 模板改造）
// 构建前后端镜像推送 Harbor(harbor.fuhua91.com/live)，并 SSH 到宝塔服务器(192.168.2.226)
// 执行 /root/deploy.sh 拉取镜像更新容器。
//
// Jenkins 凭据要求:
//   - harbor-live-push     : Username with password，Harbor 项目 live 的 robot 账号
//                            (robot$live+live / harbor.json 中的 secret)
//   - deploy-server-ssh-key: SSH Username with private key，可登录 root@192.168.2.226
//
// 服务器要求: /root/deploy.sh 已就位（见 deploy/deploy.sh），首次已手动跑通
pipeline {
  agent any

  options {
    timestamps()
    disableConcurrentBuilds()
  }

  parameters {
    choice(
      name: 'DEPLOY_MODE',
      choices: ['BUILD_AND_DEPLOY', 'DEPLOY_ONLY'],
      description: 'BUILD_AND_DEPLOY 构建新镜像并部署；DEPLOY_ONLY 部署 Harbor 中已有的镜像 tag（回滚用）'
    )
    string(
      name: 'IMAGE_TAG',
      defaultValue: '',
      description: '要部署的镜像 tag。DEPLOY_ONLY 必填；BUILD_AND_DEPLOY 留空则使用当前 commit'
    )
  }

  environment {
    APP_NAME            = 'live'
    REGISTRY_HOST       = 'harbor.fuhua91.com'
    REGISTRY_NAMESPACE  = 'live'
    BACKEND_IMAGE       = "${REGISTRY_HOST}/${REGISTRY_NAMESPACE}/backend"
    FRONTEND_IMAGE      = "${REGISTRY_HOST}/${REGISTRY_NAMESPACE}/frontend"
    LIVEWEB_IMAGE       = "${REGISTRY_HOST}/${REGISTRY_NAMESPACE}/live-web"
    DEPLOY_HOST         = 'root@192.168.2.226'
    BIN_NAME            = 'kratos-admin'
    APP_BASE            = 'live'      // 前端 vite base 与 nginx 服务名前缀
    PNPM_VERSION        = '10.15.1'
    DOCKER_BUILDKIT     = '1'
  }

  stages {
    stage('Checkout') {
      steps {
        checkout scm
      }
    }

    stage('Prepare') {
      steps {
        script {
          env.GIT_COMMIT_SHORT = sh(script: 'git rev-parse --short=12 HEAD', returnStdout: true).trim()
          env.VERSION = sh(script: 'git describe --tags --always --dirty', returnStdout: true).trim()

          if (params.DEPLOY_MODE == 'DEPLOY_ONLY') {
            if (!params.IMAGE_TAG?.trim()) {
              error('IMAGE_TAG is required when DEPLOY_MODE=DEPLOY_ONLY')
            }
            env.DEPLOY_IMAGE_TAG = params.IMAGE_TAG.trim()
          } else {
            env.DEPLOY_IMAGE_TAG = params.IMAGE_TAG?.trim() ? params.IMAGE_TAG.trim() : env.GIT_COMMIT_SHORT
          }

          echo "Deploy mode: ${params.DEPLOY_MODE}"
          echo "Backend : ${env.BACKEND_IMAGE}:${env.DEPLOY_IMAGE_TAG}"
          echo "Frontend: ${env.FRONTEND_IMAGE}:${env.DEPLOY_IMAGE_TAG}"
          echo "LiveWeb : ${env.LIVEWEB_IMAGE}:${env.DEPLOY_IMAGE_TAG}"
        }
      }
    }

    stage('Test') {
      when {
        expression { params.DEPLOY_MODE == 'BUILD_AND_DEPLOY' }
      }
      steps {
        sh '''
          go env -w GOPROXY=https://goproxy.cn,direct
          go test ./...
        '''
      }
    }

    stage('Build Frontend') {
      when {
        expression { params.DEPLOY_MODE == 'BUILD_AND_DEPLOY' }
      }
      steps {
        // 容器内构建 dist（vite base 由 web/.env.production 的 VITE_APP_BASE=/admin/ 控制），
        // 并渲染前端 nginx 配置（/api 转发到 live-backend:8000）
        sh '''
          docker run --rm \
            -v "$PWD/web:/app" -w /app \
            -e COREPACK_NPM_REGISTRY=https://registry.npmmirror.com \
            -e npm_config_registry=https://registry.npmmirror.com \
            -v kra-pnpm-store:/root/.local/share/pnpm/store \
            docker.m.daocloud.io/node:20-slim \
            bash -lc "corepack enable && corepack prepare pnpm@$PNPM_VERSION --activate && pnpm install --frozen-lockfile && pnpm build"
          sed "s/\\${KRA_APP}/$APP_BASE/g" web/.docker-compose/nginx/conf.d/my.conf > web/nginx.k8s.conf
        '''
      }
    }

    stage('Build Live Web') {
      when {
        expression { params.DEPLOY_MODE == 'BUILD_AND_DEPLOY' }
      }
      steps {
        // PC 直播用户端与后端同仓维护，确保当前提交中的接口与页面一起发布。
        // HTTP/WS 均请求同源 /api，由站点 nginx 去前缀转发到后端。
        sh '''
          docker run --rm \
            -v "$PWD/frontend:/app" -w /app \
            -e npm_config_registry=https://registry.npmmirror.com \
            docker.m.daocloud.io/node:20-slim \
            bash -lc "npm ci --no-audit --no-fund && npm run build"
        '''
      }
    }

    stage('Build Images') {
      when {
        expression { params.DEPLOY_MODE == 'BUILD_AND_DEPLOY' }
      }
      steps {
        sh '''
          CGO_ENABLED=0 go build -ldflags "-X main.Version=${VERSION}" -o bin/${BIN_NAME} ./cmd
          docker build \
            --build-arg BIN_NAME=${BIN_NAME} \
            --tag ${BACKEND_IMAGE}:${DEPLOY_IMAGE_TAG} \
            --tag ${BACKEND_IMAGE}:latest \
            .
          docker build \
            --tag ${FRONTEND_IMAGE}:${DEPLOY_IMAGE_TAG} \
            --tag ${FRONTEND_IMAGE}:latest \
            web
          docker build \
            --tag ${LIVEWEB_IMAGE}:${DEPLOY_IMAGE_TAG} \
            --tag ${LIVEWEB_IMAGE}:latest \
            frontend
        '''
      }
    }

    stage('Push Images') {
      when {
        expression { params.DEPLOY_MODE == 'BUILD_AND_DEPLOY' }
      }
      steps {
        withCredentials([usernamePassword(credentialsId: 'harbor-live-push', usernameVariable: 'HARBOR_USER', passwordVariable: 'HARBOR_PASS')]) {
          sh '''
            echo "${HARBOR_PASS}" | docker login "${REGISTRY_HOST}" -u "${HARBOR_USER}" --password-stdin
            docker push ${BACKEND_IMAGE}:${DEPLOY_IMAGE_TAG}
            docker push ${BACKEND_IMAGE}:latest
            docker push ${FRONTEND_IMAGE}:${DEPLOY_IMAGE_TAG}
            docker push ${FRONTEND_IMAGE}:latest
            docker push ${LIVEWEB_IMAGE}:${DEPLOY_IMAGE_TAG}
            docker push ${LIVEWEB_IMAGE}:latest
            docker logout "${REGISTRY_HOST}"
          '''
        }
      }
    }

    stage('Deploy') {
      steps {
        sshagent(credentials: ['deploy-server-ssh-key']) {
          sh '''
            ssh -o StrictHostKeyChecking=no ${DEPLOY_HOST} "bash /root/deploy.sh ${DEPLOY_IMAGE_TAG}"
          '''
        }
      }
    }
  }

  post {
    success {
      echo "Deployed ${BACKEND_IMAGE}:${DEPLOY_IMAGE_TAG} / ${FRONTEND_IMAGE}:${DEPLOY_IMAGE_TAG} / ${LIVEWEB_IMAGE}:${DEPLOY_IMAGE_TAG}"
    }
  }
}
