pipeline {
  agent any

  options {
    timestamps()
    disableConcurrentBuilds()
  }

  parameters {
    choice(
      name: 'DEPLOY_MODE',
      choices: ['BUILD_AND_DEPLOY', 'DEPLOY_ONLY'],
      description: 'BUILD_AND_DEPLOY builds and deploys a new image; DEPLOY_ONLY deploys an existing Harbor image tag'
    )
    string(
      name: 'IMAGE_TAG',
      defaultValue: '',
      description: 'Image tag to deploy. Required for DEPLOY_ONLY; empty BUILD_AND_DEPLOY uses current commit'
    )
  }

  environment {
    APP_NAME = 'big-party-rpc-script'
    REGISTRY_HOST = '192.168.2.160:8088'
    REGISTRY_NAMESPACE = 'zhoubao'
    IMAGE_REPOSITORY = "${REGISTRY_HOST}/${REGISTRY_NAMESPACE}/${APP_NAME}"
    DEPLOY_HOST = 'root@192.168.2.226'
    DEPLOY_DIR = "/opt/${APP_NAME}"
    GITLAB_PROXY_HOST = '192.168.2.160'
    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 "Image: ${env.IMAGE_REPOSITORY}:${env.DEPLOY_IMAGE_TAG}"
        }
      }
    }

    stage('Test') {
      when {
        expression { params.DEPLOY_MODE == 'BUILD_AND_DEPLOY' }
      }
      steps {
        withCredentials([sshUserPrivateKey(credentialsId: 'gitlab-go-deps-ssh-key', keyFileVariable: 'GIT_SSH_KEY')]) {
          sh '''
            git config --global url."git@gitlab.fuhua91.com:".insteadOf "https://gitlab.fuhua91.com/"
            git config --global url."git@gitlab.fuhua91.com:".insteadOf "http://gitlab.fuhua91.com/"
            export GIT_SSH_COMMAND="ssh -i ${GIT_SSH_KEY} -o StrictHostKeyChecking=no"
            go env -w GOPROXY=https://goproxy.cn,direct
            go env -w GOPRIVATE=gitlab.fuhua91.com
            go env -w GOINSECURE=gitlab.fuhua91.com
            go test ./...
          '''
        }
      }
    }

    stage('Build Image') {
      when {
        expression { params.DEPLOY_MODE == 'BUILD_AND_DEPLOY' }
      }
      steps {
        withCredentials([sshUserPrivateKey(credentialsId: 'gitlab-go-deps-ssh-key', keyFileVariable: 'GIT_SSH_KEY')]) {
          sh '''
            docker build \
              --file deploy/Dockerfile \
              --add-host gitlab.fuhua91.com:${GITLAB_PROXY_HOST} \
              --secret id=git_ssh_key,src=${GIT_SSH_KEY} \
              --build-arg VERSION=${VERSION} \
              --tag ${IMAGE_REPOSITORY}:${DEPLOY_IMAGE_TAG} \
              --tag ${IMAGE_REPOSITORY}:latest \
              .
          '''
        }
      }
    }

    stage('Push Image') {
      when {
        expression { params.DEPLOY_MODE == 'BUILD_AND_DEPLOY' }
      }
      steps {
        withCredentials([usernamePassword(credentialsId: 'docker-registry', usernameVariable: 'REGISTRY_USER', passwordVariable: 'REGISTRY_PASS')]) {
          sh '''
            echo "${REGISTRY_PASS}" | docker login "${REGISTRY_HOST}" -u "${REGISTRY_USER}" --password-stdin
            docker push ${IMAGE_REPOSITORY}:${DEPLOY_IMAGE_TAG}
            docker push ${IMAGE_REPOSITORY}:latest
          '''
        }
      }
    }

    stage('Deploy') {
      steps {
        withCredentials([usernamePassword(credentialsId: 'docker-registry', usernameVariable: 'REGISTRY_USER', passwordVariable: 'REGISTRY_PASS')]) {
          sshagent(credentials: ['deploy-server-ssh-key']) {
            sh '''
              ssh -o StrictHostKeyChecking=no ${DEPLOY_HOST} "mkdir -p ${DEPLOY_DIR}/deploy ${DEPLOY_DIR}/configs ${DEPLOY_DIR}/logs"
              scp -O -o StrictHostKeyChecking=no deploy/docker-compose.yaml ${DEPLOY_HOST}:${DEPLOY_DIR}/deploy/docker-compose.yaml
              scp -O -o StrictHostKeyChecking=no configs/config.yaml ${DEPLOY_HOST}:${DEPLOY_DIR}/configs/config.yaml
              printf '%s' "${REGISTRY_PASS}" | ssh -o StrictHostKeyChecking=no ${DEPLOY_HOST} "docker login '${REGISTRY_HOST}' -u '${REGISTRY_USER}' --password-stdin"
              ssh -o StrictHostKeyChecking=no ${DEPLOY_HOST} "
                cd ${DEPLOY_DIR}/deploy &&
                printf '%s\\n' \
                  'IMAGE_REPOSITORY=${IMAGE_REPOSITORY}' \
                  'IMAGE_TAG=${DEPLOY_IMAGE_TAG}' \
                  'HTTP_PORT=20200' \
                  'GRPC_PORT=20201' \
                  'CONFIG_FILE=../configs/config.yaml' \
                  'LOG_DIR=../logs' > .env &&
                docker-compose pull &&
                docker-compose up -d &&
                docker image prune -f
              "
            '''
          }
        }
      }
    }
  }

  post {
    success {
      echo "Deployed ${IMAGE_REPOSITORY}:${DEPLOY_IMAGE_TAG}"
    }
  }
}
