// note-manager Jenkins Pipeline
// 项目：Go/Gin + SQLite（CGO），部署端口 9090

pipeline {
    agent any

    environment {
        // ─── 基础配置 ───
        APP_NAME      = 'note-manager'
        GO_VERSION    = '1.21'
        GIT_REPO      = 'https://git.cnbugs.com/AI-Agent/note-manager.git'
        GIT_BRANCH    = 'main'
        // ─── 部署配置（敏感信息用 Jenkins Credentials）───
        DEPLOY_HOST   = credentials('deploy-host')
        DEPLOY_USER   = credentials('deploy-user')
        DEPLOY_PATH   = '/vol1/Project/note-manager'
        SERVICE_PORT  = '9090'
        // ─── 构建产物 ───
        BUILD_DIR     = 'dist'
    }

    options {
        timestamps()
        timeout(time: 15, unit: 'MINUTES')
        disableConcurrentBuilds()
        buildDiscarder(logRotator(numToKeepStr: '10'))
    }

    stages {

        // ━━━━━━━━ 拉取代码 ━━━━━━━━
        stage('Checkout') {
            steps {
                git branch: "${GIT_BRANCH}",
                    url: "${GIT_REPO}",
                    credentialsId: 'git-cnbugs-credentials'
                sh 'echo "分支: ${GIT_BRANCH} | 提交: $(git rev-parse --short HEAD)"'
            }
        }

        // ━━━━━━━━ 代码检查 ━━━━━━━━
        stage('Lint') {
            steps {
                sh '''
                    docker run --rm \
                        -v "$PWD":/app \
                        -w /app \
                        golang:${GO_VERSION}-alpine \
                        sh -c "go fmt ./... && go vet ./..."
                '''
            }
        }

        // ━━━━━━━━ 单元测试 ━━━━━━━━
        stage('Test') {
            steps {
                sh '''
                    docker run --rm \
                        -v "$PWD":/app \
                        -w /app \
                        -e CGO_ENABLED=1 \
                        golang:${GO_VERSION} \
                        go test -v -race -coverprofile=coverage.out ./...
                '''
            }
            post {
                always {
                    archiveArtifacts artifacts: 'coverage.out', allowEmptyArchive: true
                }
            }
        }

        // ━━━━━━━━ 编译构建 ━━━━━━━━
        stage('Build') {
            steps {
                sh '''
                    rm -rf ${BUILD_DIR} && mkdir -p ${BUILD_DIR}

                    VERSION=$(git describe --tags --always --dirty 2>/dev/null || git rev-parse --short HEAD)
                    BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
                    COMMIT=$(git rev-parse --short HEAD)

                    echo "━━━ 构建信息 ━━━"
                    echo "版本: ${VERSION}"
                    echo "提交: ${COMMIT}"
                    echo "时间: ${BUILD_TIME}"

                    # go-sqlite3 需要 CGO_ENABLED=1，用完整 golang 镜像确保 gcc 可用
                    docker run --rm \
                        -v "$PWD":/app \
                        -w /app \
                        -e CGO_ENABLED=1 \
                        -e GOOS=linux \
                        -e GOARCH=amd64 \
                        golang:${GO_VERSION} \
                        go build \
                            -ldflags="-s -w \
                                -X main.Version=${VERSION} \
                                -X main.BuildTime=${BUILD_TIME} \
                                -X main.Commit=${COMMIT}" \
                            -o ${BUILD_DIR}/${APP_NAME} \
                            ./...

                    file ${BUILD_DIR}/${APP_NAME}
                    ls -lh ${BUILD_DIR}/${APP_NAME}
                '''
            }
        }

        // ━━━━━━━━ 打包发布 ━━━━━━━━
        stage('Package') {
            steps {
                sh '''
                    VERSION=$(git describe --tags --always --dirty 2>/dev/null || git rev-parse --short HEAD)

                    mkdir -p ${BUILD_DIR}/package

                    # 复制运行所需文件
                    cp ${BUILD_DIR}/${APP_NAME}     ${BUILD_DIR}/package/
                    cp -r config                    ${BUILD_DIR}/package/
                    cp -r web                       ${BUILD_DIR}/package/

                    # 生成启动脚本
                    cat > ${BUILD_DIR}/package/start.sh << 'STARTSCRIPT'
#!/bin/bash
APP_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$APP_DIR"

export PORT=${SERVICE_PORT}
export DB_PATH=data/notes.db
export UPLOAD_DIR=uploads
export ADMIN_PASS=${ADMIN_PASS:-admin123}

mkdir -p data uploads

echo "启动 note-manager ..."
./note-manager
STARTSCRIPT
                    chmod +x ${BUILD_DIR}/package/start.sh

                    # 打 tar 包
                    cd ${BUILD_DIR}/package
                    tar czf ${WORKSPACE}/${APP_NAME}-${VERSION}-linux-amd64.tar.gz .
                    cd ${WORKSPACE}

                    echo "━━━ 发布包 ━━━"
                    ls -lh ${APP_NAME}-${VERSION}-linux-amd64.tar.gz
                '''
            }
            post {
                success {
                    archiveArtifacts artifacts: "${APP_NAME}-*-linux-amd64.tar.gz", fingerprint: true
                }
            }
        }

        // ━━━━━━━━ 部署（需手动确认）━━━━━━━━
        stage('Deploy') {
            when {
                branch 'main'
            }
            input {
                message '确认部署到生产环境？'
                ok '部署'
            }
            steps {
                sh '''
                    VERSION=$(git describe --tags --always --dirty 2>/dev/null || git rev-parse --short HEAD)
                    PACKAGE="${APP_NAME}-${VERSION}-linux-amd64.tar.gz"

                    echo "━━━ 部署到 ${DEPLOY_HOST} ━━━"

                    # 上传发布包
                    scp -o StrictHostKeyChecking=no \
                        ${PACKAGE} \
                        ${DEPLOY_USER}@${DEPLOY_HOST}:/tmp/${PACKAGE}

                    # 远程执行部署
                    ssh -o StrictHostKeyChecking=no ${DEPLOY_USER}@${DEPLOY_HOST} "bash -s" << REMOTE_DEPLOY
                        set -e
                        echo "停止旧服务..."
                        pkill -f 'note-manager' || true
                        sleep 1

                        echo "备份旧版本..."
                        if [ -f ${DEPLOY_PATH}/note-manager ]; then
                            cp ${DEPLOY_PATH}/note-manager ${DEPLOY_PATH}/note-manager.bak
                        fi

                        echo "解压新版本..."
                        mkdir -p ${DEPLOY_PATH}
                        cd ${DEPLOY_PATH}
                        tar xzf /tmp/${PACKAGE}
                        rm -f /tmp/${PACKAGE}

                        echo "启动服务..."
                        cd ${DEPLOY_PATH}
                        PORT=${SERVICE_PORT} nohup ./note-manager > ${DEPLOY_PATH}/app.log 2>&1 &

                        sleep 2
                        if curl -sf http://localhost:${SERVICE_PORT}/ > /dev/null 2>&1; then
                            echo "✅ 服务启动成功！端口: ${SERVICE_PORT}"
                        else
                            echo "❌ 服务启动失败，查看日志:"
                            tail -20 ${DEPLOY_PATH}/app.log
                            exit 1
                        fi
REMOTE_DEPLOY

                    echo "━━━ 部署完成 ━━━"
                '''
            }
        }
    }

    post {
        success {
            echo '✅ Pipeline 执行成功'
        }
        failure {
            echo '❌ Pipeline 执行失败'
        }
        always {
            cleanWs()
        }
    }
}
