pipeline {
    agent any
    parameters {
        choice(name: 'TYPE', choices: ['client', 'admin'], description: '选择要部署的应用类型')
        choice(name: 'APP_NAME', choices: ['client-api', 'admin-api'], description: '选择要部署的应用名称')
    }
    environment {
        // 远程服务器信息
        REMOTE_HOST = '47.238.171.2'
        REMOTE_USER = 'root'
        // 应用信息
        APP_NAME = "${params.APP_NAME}"
        TYPE = "${params.TYPE}"
        // 远程服务器应用目录
        REMOTE_APP_DIR = '/app'
    }

    stages {
        stage('打印环境信息') {
            steps {
                echo "开始部署流程..."
                echo "应用名称: ${APP_NAME}"
                echo "应用类型: ${TYPE}"
                echo "远程服务器: ${REMOTE_USER}@${REMOTE_HOST}"
                echo "远程应用目录: ${REMOTE_APP_DIR}"
                echo "当前工作目录: ${WORKSPACE}"
            }
        }
        stage('构建Docker镜像') {
            steps {

                echo "正在构建 ${APP_NAME} Docker镜像..."
                sh "docker build -t ${APP_NAME} -f Dockerfile ."

                // 列出Docker镜像以确认构建成功
                sh "docker images | grep ${APP_NAME}"
            }
        }

        stage('导出Docker镜像') {
            steps {
                echo "正在导出 ${APP_NAME} Docker镜像..."
                sh "docker save ${APP_NAME} > ${APP_NAME}.tar"

                // 检查tar文件大小以确认导出成功
                sh "ls -lh ${APP_NAME}.tar"
            }
        }

        stage('传输镜像到远程服务器') {
            steps {
                echo "正在传输镜像到远程服务器 ${REMOTE_USER}@${REMOTE_HOST}..."

                // 使用withCredentials为scp命令提供SSH凭据
                // 注意：需要在Jenkins中配置名为'remote-server'的SSH凭据
                withCredentials([sshUserPrivateKey(credentialsId: 'ssh-private-key', keyFileVariable: 'SSH_KEY')]) {
                    sh """
                        scp -i ${SSH_KEY} -o StrictHostKeyChecking=no ${WORKSPACE}/${APP_NAME}.tar ${REMOTE_USER}@${REMOTE_HOST}:/app/
                    """
                }
            }
        }

        stage('在远程服务器上加载镜像') {
            steps {
                echo "在远程服务器上加载Docker镜像..."

                // 使用withCredentials为ssh命令提供SSH凭据
                withCredentials([sshUserPrivateKey(credentialsId: 'ssh-private-key', keyFileVariable: 'SSH_KEY')]) {
                    sh """
                        ssh -i ${SSH_KEY} -o StrictHostKeyChecking=no ${REMOTE_USER}@${REMOTE_HOST} '
                            docker load < /app/${APP_NAME}.tar &&
                            rm /app/${APP_NAME}.tar
                        '
                    """
                }
            }
        }

        stage('在远程服务器上部署应用') {
            steps {
                echo "在远程服务器上重新部署应用..."

                // 使用withCredentials为ssh命令提供SSH凭据
                withCredentials([sshUserPrivateKey(credentialsId: 'ssh-private-key', keyFileVariable: 'SSH_KEY')]) {
                    sh """
                        ssh -i ${SSH_KEY} -o StrictHostKeyChecking=no ${REMOTE_USER}@${REMOTE_HOST} '
                            cd ${REMOTE_APP_DIR} &&
                            docker compose up -d --force-recreate ${APP_NAME}
                        '
                    """
                }
            }
        }

        stage('执行数据库迁移') {
            steps {
                echo "在${APP_NAME}容器中执行数据库迁移..."

                // 使用withCredentials为ssh命令提供SSH凭据
                withCredentials([sshUserPrivateKey(credentialsId: 'ssh-private-key', keyFileVariable: 'SSH_KEY')]) {
                    sh """
                        ssh -i ${SSH_KEY} -o StrictHostKeyChecking=no ${REMOTE_USER}@${REMOTE_HOST} '
                            cd ${REMOTE_APP_DIR} &&
                            docker exec ${APP_NAME} alembic upgrade head
                        '
                    """
                }
            }
        }
    }

    post {
        success {
            echo "流水线成功执行! ${APP_NAME} 已成功部署到 ${REMOTE_HOST}"
        }
        failure {
            echo "流水线执行失败，请检查日志获取详细信息"
        }
        always {
            // 清理本地Docker镜像以节省空间
            sh "docker rmi ${APP_NAME} || true"
            cleanWs()
        }
    }
}
