properties([
    buildDiscarder(logRotator(numToKeepStr: '10'))
])

def bunBinDir() {
    if (isUnix()) {
        return "${env.HOME}/.bun/bin"
    }
    return "${env.USERPROFILE}/.bun/bin"
}

def withBun(Closure body) {
    def sep = isUnix() ? ':' : ';'
    withEnv(["PATH=${bunBinDir()}${sep}${env.PATH}"]) {
        body()
    }
}

def checkBun() {
    if (isUnix()) {
        sh 'bun -v'
    } else {
        bat 'bun -v'
    }
}

def writeBuildMetadata() {
    if (isUnix()) {
        sh '''
            bun --eval "await Bun.write('src/buildInfo.json', JSON.stringify({ buildNumber: process.env.BUILD_NUMBER || 'dev' }, null, 2) + '\\n')"
        '''
    } else {
        bat '''
            bun --eval "await Bun.write('src/buildInfo.json', JSON.stringify({ buildNumber: process.env.BUILD_NUMBER || 'dev' }, null, 2) + '\\n')"
        '''
    }
}

def runBuild(buildCommand) {
    def releaseBaseUrl =
        "https://dist.farmcontrol.app/jenkins/farmcontrol/farmcontrol-ui"
    withEnv([
        "VITE_BUILD_NUMBER=${env.BUILD_NUMBER ?: 'dev'}",
        'NODE_ENV=production',
        "ELECTROBUN_RELEASE_BASE_URL=${releaseBaseUrl}",
    ]) {
        if (isUnix()) {
            sh buildCommand
        } else {
            bat buildCommand
        }
    }
}

def deploy() {
    node('ubuntu') {
        try {
            stage('Checkout (Ubuntu)') {
                checkout scm
            }

            stage('Setup Node.js (Ubuntu)') {
                nodejs(nodeJSInstallationName: 'Node23') {
                    sh 'node -v'
                    sh 'pnpm -v'
                }
            }

            stage('Install Dependencies (Ubuntu)') {
                nodejs(nodeJSInstallationName: 'Node23') {
                    sh 'pnpm install --frozen-lockfile --production=false'
                }
            }

            stage('Build (Ubuntu)') {
                nodejs(nodeJSInstallationName: 'Node23') {
                    sh "VITE_BUILD_NUMBER=${env.BUILD_NUMBER} NODE_ENV=production pnpm build:cloudflare"
                }
            }

            stage('Deploy (Ubuntu)') {
                nodejs(nodeJSInstallationName: 'Node23') {
                    withCredentials([string(credentialsId: 'cloudflare-api-token', variable: 'CLOUDFLARE_API_TOKEN')]) {
                        sh 'pnpm wrangler pages deploy build --branch main'
                    }
                }
            }
        } finally {
            cleanWs()
        }
    }
}

def prepareMacBuildWorkspace() {
    if (isUnix()) {
        sh '''
            df -h .
            for vol in /Volumes/Farm\\ Control*; do
              if [ -d "$vol" ]; then
                hdiutil detach "$vol" -force || true
              fi
            done
            rm -rf build/stable-macos-*/.dmg-staging build/stable-macos-*/.finalize-dmg-staging 2>/dev/null || true
        '''
    }
}

def buildOnLabel(label, buildCommand, bundleCef = false) {
    def cefLabel = bundleCef ? 'cef' : 'native'
    return {
        node(label) {
            try {
                stage("Checkout (${label}/${cefLabel})") {
                    checkout scm
                }

                withBun {
                    stage("Check Bun (${label}/${cefLabel})") {
                        checkBun()
                    }

                    if (label.startsWith('macos')) {
                        stage("Prepare macOS workspace (${label}/${cefLabel})") {
                            prepareMacBuildWorkspace()
                        }
                    }

                    stage("Install Dependencies (${label}/${cefLabel})") {
                        if (isUnix()) {
                            sh 'bun install --frozen-lockfile'
                        } else {
                            bat 'bun install --frozen-lockfile'
                        }
                    }

                    stage("Write Build Metadata (${label}/${cefLabel})") {
                        writeBuildMetadata()
                    }

                    stage("Build (${label}/${cefLabel})") {
                        withEnv(["ELECTROBUN_BUNDLE_CEF=${bundleCef ? 'true' : 'false'}"]) {
                            runBuild(buildCommand)
                        }
                    }
                }

                stage("Archive Artifacts (${label}/${cefLabel})") {
                    archiveArtifacts artifacts: 'app_dist/farmcontrol-*', fingerprint: true
                }
            } finally {
                cleanWs()
            }
        }
    }
}

def buildMacOnLabel(label, targetArch, bundleCef = false) {
    return buildOnLabel(label, "ELECTROBUN_TARGET_ARCH=${targetArch} bun run build:app:mac", bundleCef)
}

def setBuildNameFromPackageVersion() {
    node('ubuntu') {
        stage('Set Build Name') {
            checkout scm
            withBun {
                checkBun()
                def version = sh(
                    script: "bun --eval \"console.log(JSON.parse(await Bun.file('package.json').text()).version)\"",
                    returnStdout: true
                ).trim()
                def buildName = "v${version}-b${env.BUILD_NUMBER}"
                currentBuild.displayName = buildName
                echo "Build name set to: ${buildName}"
            }
        }
    }
}

try {
    setBuildNameFromPackageVersion()

    parallel(
        'Windows Build': buildOnLabel('windows', 'bun run build:app', false),
        'Windows CEF Build': buildOnLabel('windows', 'bun run build:app', true),
        'MacOS x64 Build': buildMacOnLabel('macos', 'x64', false),
        'MacOS x64 CEF Build': buildMacOnLabel('macos', 'x64', true),
        'MacOS arm64 Build': buildMacOnLabel('macos', 'arm64', false),
        'MacOS arm64 CEF Build': buildMacOnLabel('macos', 'arm64', true),
        'Ubuntu Deploy': { deploy() }
    )

    echo 'All parallel stages completed successfully!'

} catch (Exception e) {
    echo "Pipeline failed: ${e.message}"
    throw e
}
