pipeline {
    agent any

    environment {
        // 环境变量定义
        PROJECT_NAME = 'timeline-frontend'
        DOCKER_REGISTRY = 'timeline-registry:5000'
        DOCKER_IMAGE = "${DOCKER_REGISTRY}/${PROJECT_NAME}"
    }

    parameters {
        // 构建参数
        choice(
            name: 'DEPLOY_TARGET',
            choices: ['dev', 'staging', 'prod'],
            description: '选择部署环境'
        )
        string(
            name: 'GIT_COMMIT',
            defaultValue: '',
            description: '指定 Git Commit SHA 进行构建（留空则使用最新提交）'
        )
    }

    stages {
        stage('Checkout') {
            steps {
                script {
                    if (params.GIT_COMMIT) {
                        checkout scm
                        sh "git reset --hard ${params.GIT_COMMIT}"
                    } else {
                        checkout scm
                    }
                }
                echo "当前构建的 Git Commit: ${env.GIT_COMMIT}"
            }
        }

        stage('Build timeline-frontend dist') {
            steps {
                script {
                    def workspace = sh(script: "pwd", returnStdout: true).trim()
                    echo "当前工作空间路径:  ${workspace}"

                    // 确保路径正确
                    sh "ls -la  ${workspace}"

                    // 使用 Jenkins Node.js 插件
                    nodejs('NodeJS-18') {
                        // 检查是否存在 package.json
                        if (fileExists('package.json')) {
                            echo "package.json found"


                            // 使用 pnpm 安装依赖
                            sh 'npm install'

                            // 构建项目
                            sh 'npm run build'

                            // 检查 dist 目录是否存在
                            if (!fileExists('dist')) {
                                error('ERROR: dist directory does not exist after build')
                            } else {
                                echo 'Build completed successfully, dist directory exists'
                            }
                        } else {
                            error('package.json not found')
                        }
                    }
                }
            }
        }

        stage('Build Docker Image') {
            steps {
                script {
                    def imageTag = "${BUILD_NUMBER}-${env.GIT_COMMIT.take(7)}"
                    env.IMAGE_TAG = imageTag

                    // 创建一个简单的 nginx 配置（可选）
                    sh '''
                        cat > nginx.conf << 'EOF'
                        events {
                            worker_connections 1024;
                        }

                        http {
                            include       /etc/nginx/mime.types;
                            default_type  application/octet-stream;

                            server {
                                listen       80;
                                server_name  localhost;

                                location / {
                                    root   /usr/share/nginx/html;
                                    index  index.html index.htm;
                                    try_files $uri $uri/ /index.html;
                                }

                                error_page   500 502 503 504  /50x.html;
                                location = /50x.html {
                                    root   /usr/share/nginx/html;
                                }
                            }
                        }
                        EOF
                    '''

                    sh """
                        docker build -t ${DOCKER_IMAGE}:${imageTag} .
                        docker tag ${DOCKER_IMAGE}:${imageTag} ${DOCKER_IMAGE}:latest
                    """
                }
            }
        }

        stage('Push Docker Image') {
            steps {
                script {
                    withCredentials([usernamePassword(credentialsId: 'docker-registry-credentials',
                                                     usernameVariable: 'DOCKER_USER',
                                                     passwordVariable: 'DOCKER_PASS')]) {
                        sh 'echo $DOCKER_PASS | docker login $DOCKER_REGISTRY -u $DOCKER_USER --password-stdin'
                        sh "docker push ${DOCKER_IMAGE}:${env.IMAGE_TAG}"
                        sh "docker push ${DOCKER_IMAGE}:latest"
                    }
                }
            }
        }

        stage('Deploy to Environment') {
            parallel {
                stage('Deploy to Dev') {
                    when {
                        expression { params.DEPLOY_TARGET == 'dev' }
                    }
                    steps {
                        deployToEnvironment('dev')
                    }
                }

                stage('Deploy to Staging') {
                    when {
                        anyOf {
                            expression { params.DEPLOY_TARGET == 'staging' }
                            expression { params.DEPLOY_TARGET == 'prod' }
                        }
                    }
                    steps {
                        deployToEnvironment('staging')
                    }
                }

                stage('Deploy to Production') {
                    when {
                        expression { params.DEPLOY_TARGET == 'prod' }
                    }
                    steps {
                        script {
                            input message: "确定要部署到生产环境吗？", ok: "是", parameters: [
                                choice(name: 'CONFIRM_DEPLOY', choices: ['yes', 'no'], description: '确认部署')
                            ]
                            if (params.CONFIRM_DEPLOY == 'yes') {
                                deployToEnvironment('prod')
                            } else {
                                error "部署被取消"
                            }
                        }
                    }
                }
            }
        }
    }

    post {
        always {
            // 清理构建产物
            cleanWs()
        }

        success {
            script {
                def slackMessage = """
                    *✅ 构建成功*
                    项目: ${PROJECT_NAME}
                    构建: ${BUILD_NUMBER}
                    分支: ${env.BRANCH_NAME}
                    提交: ${env.GIT_COMMIT}
                    镜像: ${DOCKER_IMAGE}:${env.IMAGE_TAG}
                """
                // 发送成功通知（如果配置了 Slack 通知）
                // slackSend(channel: '#builds', color: 'good', message: slackMessage)
            }
        }

        failure {
            script {
                def slackMessage = """
                    *❌ 构建失败*
                    项目: ${PROJECT_NAME}
                    构建: ${BUILD_NUMBER}
                    分支: ${env.BRANCH_NAME}
                    提交: ${env.GIT_COMMIT}
                    错误: ${currentBuild.description ?: '构建失败'}
                """
                // 发送失败通知（如果配置了 Slack 通知）
                // slackSend(channel: '#builds', color: 'danger', message: slackMessage)
            }
        }

        cleanup {
            // 清理 Docker 镜像
            script {
                sh """
                    docker rmi -f ${DOCKER_IMAGE}:${env.IMAGE_TAG} || true
                    docker rmi -f ${DOCKER_IMAGE}:latest || true
                """
            }
        }
    }
}

// 公共函数定义
def deployToEnvironment(String env) {
    script {
        // 根据环境设置部署参数
        def containerName = "${PROJECT_NAME}-${env}"
        def imageToDeploy = "${DOCKER_IMAGE}:${env.IMAGE_TAG}"

        // 停止现有容器
        sh """
            docker stop ${containerName} || true
            docker rm ${containerName} || true
        """

        // 运行新容器
        sh """
            docker run -d \
              --name ${containerName} \
              --restart unless-stopped \
              -p ${getPortForEnvironment(env)}:80 \
              ${imageToDeploy}
        """

        // 验证部署
        sh """
            echo "等待容器启动..."
            sleep 10
            docker ps | grep ${containerName}
            docker logs ${containerName}
        """
    }
}

// 获取环境对应端口的辅助函数
def getPortForEnvironment(String env) {
    switch(env) {
        case 'dev':
            return '3001'
        case 'staging':
            return '3002'
        case 'prod':
            return '80'
        default:
            return '80'
    }
}
