pipeline {
    agent { label 'mac' }
    
    triggers {
        pollSCM('* * * * *')
    }

    parameters {
        string(name: 'PRJ_URL', defaultValue: '<https://github.com/Geekble-Game/SerpentOfTheEnd-client.git>', description: 'GitHub repository URL')
        string(name: 'BRANCH', defaultValue: 'develop', description: 'Branch to build')
        string(name: 'UNITY_VER', defaultValue: '6000.0.26f1', description: 'Unity Editor version')
        string(name: 'BUILD_ROOT', defaultValue: '/Users/msg/Desktop/build', description: 'Build output root directory')
        booleanParam(name: 'UNITY_BUILD_AAB', defaultValue: true, description: 'Build Android App Bundle (AAB)')
    }

    environment {
        UNITY_PATH = "/Applications/Unity/Hub/Editor/${params.UNITY_VER}/Unity.app/Contents/MacOS/Unity"
    }
    
    options {
        disableConcurrentBuilds()
    }

    stages {
        stage('Clean Workspace') {
            steps {
                cleanWs()
            }
        }
        
        stage('Checkout with Submodules') {
            steps {
                checkout([
                    $class: 'GitSCM',
                    branches: [[name: "*/${params.BRANCH}"]],
                    userRemoteConfigs: [[
                        url: "${params.PRJ_URL}",
                        credentialsId: 'SerpentOfTheEnd_Jenkins_Polling_TOKEN'
                    ]],
                    extensions: [
                        [$class: 'SubmoduleOption', recursiveSubmodules: true, trackingSubmodules: true],
                        [$class: 'RelativeTargetDirectory', relativeTargetDir: 'SerpentOfTheEnd-client']
                    ]
                ])
            }
        }

        stage('Init Project Name') {
            steps {
                script {
                    def (repoName, projectName) = parseProjectInfoFromRepoUrl(params.PRJ_URL)

                    env.BUILD_REPO_NAME = repoName
                    env.BUILD_PROJECT_NAME = projectName

                    echo "[INFO] Git URL: ${params.PRJ_URL}"
                    echo "[INFO] REPO Name: ${env.BUILD_REPO_NAME}"
                    echo "[INFO] Project Name: ${env.BUILD_PROJECT_NAME}"
                    echo "[INFO] Branch Name: ${params.BRANCH}"
                }
            }
        }

        stage('Unity Version Check') {
            steps {
                sh """
                    "${env.UNITY_PATH}" -version
                """
            }
        }

        stage('Build Unity Android') {
            options {
                timeout(time: 1, unit: 'HOURS')  // 🔥 Build 단계에만 timeout 적용
            }
            steps {
                withCredentials([
                    string(credentialsId: 'keystore_pass', variable: 'KEYSTORE_PASS'),
                    string(credentialsId: 'key_alias', variable: 'KEY_ALIAS'),
                    string(credentialsId: 'key_alias_pass', variable: 'KEY_ALIAS_PASS')
                ]) {
                    script {
                        def defaultBuildPath = "${params.BUILD_ROOT}/${env.BUILD_PROJECT_NAME}/${params.BRANCH}"

                        def outputDir = "${defaultBuildPath}/Builds/android"
                        def logDir = "${defaultBuildPath}/Logs"

                        def buildName = getBuildName()
                        def ext = (params.UNITY_BUILD_AAB) ? 'aab' : 'apk'

                        def logPath = "${logDir}/${buildName}.log"
                        def filePath = "${outputDir}/${buildName}.${ext}"

                        def defaultProjectPath = "${env.WORKSPACE}/${env.BUILD_REPO_NAME}/${env.BUILD_PROJECT_NAME}"

                        def projectPath = "${defaultProjectPath}"
                        def keystorePath = "${defaultProjectPath}.keystore"

                        env.BUILD_OUTPUT_PATH = filePath
                        env.BUILD_LOG_PATH = logPath

                        withEnv([
                            "UNITY_BUILD_PATH=${filePath}",
                            "UNITY_BUILD_AAB=${params.UNITY_BUILD_AAB}",
                            "KEYSTORE_PATH=${keystorePath}",
                            "KEYSTORE_PASS=${env.KEYSTORE_PASS}",
                            "KEY_ALIAS=${env.KEY_ALIAS}",
                            "KEY_ALIAS_PASS=${env.KEY_ALIAS_PASS}"
                        ]) {
                            sh """
                                mkdir -p "${logDir}"

                                "${env.UNITY_PATH}" \
                                  -batchmode \
                                  -nographics \
                                  -projectPath "${projectPath}" \
                                  -executeMethod AndroidBuilder.BuildAndroid \
                                  -quit \
                                  -logFile "${logPath}" \
                                  -buildTarget android
                            """
                        }

                        if (!fileExists(filePath)) {
                            error "[ERROR] Build failed: ${filePath} not found"
                        }
                    }
                }
            }
        }

        stage('Upload to S3') {
            steps {
                withCredentials([
                    [$class: 'AmazonWebServicesCredentialsBinding', credentialsId: 'AWS_CREDENTIALS']
                ]) {
                    script {
                        def bucketName = "msg-game"
                        def folderName = env.BUILD_PROJECT_NAME
                        def branchName = params.BRANCH

                        def region = "ap-northeast-2"
                        def s3Path = "s3://${bucketName}/${folderName}/${branchName}/android/"
                        def outputFile = env.BUILD_OUTPUT_PATH
                        def fileName = outputFile.tokenize('/')[-1]
                        def s3Url = "<https://$>{bucketName}.s3.${region}.amazonaws.com/${folderName}/${branchName}/android/${fileName}"

                        sh """
                            export PATH=/usr/local/bin:/opt/homebrew/bin:\$PATH
                            aws s3 cp "${outputFile}" "${s3Path}" --region ${region}
                        """

                        env.BUILD_S3_URL = s3Url
                        echo "[INFO] S3 URL: ${env.BUILD_S3_URL}"
                    }
                }
            }
        }
    }

    post {
        success {
            script {
                sendSlack("success", "#36a64f")
            }
        }
        failure {
            script {
                sendSlack("failure", "#FF0000")
            }
        }
    }
}

def parseProjectInfoFromRepoUrl(repoUrl) {
    def repoName = repoUrl.tokenize('/').last().replace('.git', '')
    def projectName = repoName.replaceFirst(/-client$/, '')
    return [repoName, projectName]
}

def getBuildName() {
    def timestamp = sh(script: "date +\"%Y%m%d_%H%M%S\"", returnStdout: true).trim()

    def gitHash = ''
    def gitTag = ''

    dir("${env.WORKSPACE}/${env.BUILD_REPO_NAME}") {
        gitHash = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
        gitTag = sh(script: "git describe --tags --abbrev=0 2>/dev/null || echo no-tag", returnStdout: true).trim()
    }

    return "app_${gitTag}_${gitHash}_${timestamp}"
}

def sendSlack(String status, String color) {
    def title = (status == "success") ? "✅ *Unity Android 빌드 성공*" : "❌ *Unity Android 빌드 실패*"
    def curlBody = """{
        "text": "${title}",
        "attachments": [{
            "color": "${color}",
            "fields": [
                {"title": "Project", "value": "${env.BUILD_PROJECT_NAME}", "short": true},
                {"title": "Branch", "value": "${params.BRANCH}", "short": true},
                {"title": "Job", "value": "${env.JOB_NAME} #${env.BUILD_NUMBER}", "short": true},
                {"title": "Build File", "value": "${env.BUILD_OUTPUT_PATH}", "short": false},
                {"title": "S3 Download", "value": "${env.BUILD_S3_URL}", "short": false}
            ]
        }]
    }"""

    withCredentials([string(credentialsId: 'SLACK_WEBHOOK_URL', variable: 'SLACK_URL')]) {
        sh """
            curl -X POST -H 'Content-type: application/json' --data '${curlBody}' "$SLACK_URL"
        """
    }
}