import hudson.Util
import hudson.model.*
import com.sonymusic.*
import groovy.json.JsonOutput

def call(Map args) {
    def params = Utils.validateParams('playwrightTests', args, [
        tags: [type: String, required: true],
        frameworkEnvironment: [type: String, required: false, defaultValue: 'prod'],
        runtimeEnvironment: [type: String, required: false, defaultValue: 'lambda'],
        configEnvironment: [type: String, required: false, defaultValue: 'qa'],
        branchName: [type: String, required: false, defaultValue: '*/master'],
        frameworkRunnerTag: [type: String, required: false, defaultValue: 'latest'],
        githubUser: [type: String, required: false, defaultValue: 'theorchard'],
        reportSuffix: [type: String, required: false, defaultValue: ''],
        slackNotificationChannels: [type: List, required: false, defaultValue: []],
        envVars: [type: Map, required: false, defaultValue: [:]],
        pnpmSetupScriptName: [type: String, required: false, defaultValue: ''],
        githubPRRepo: [type: String, required: false, defaultValue: ''],
        githubPRID: [type: String, required: false, defaultValue: env.CHANGE_ID ?: '']
    ])

    def subDir = params.reportSuffix ?: 'default'

    def commitAuthor = 'Unknown'
    def commitEmail = 'unknown@example.com'
    def commitMessage = 'No commit message'

    try {
        commitAuthor = sh(script: "git log -1 --pretty=format:'%an'", returnStdout: true).trim()
        commitEmail = sh(script: "git log -1 --pretty=format:'%ae'", returnStdout: true).trim()
        commitMessage = sh(script: "git log -1 --pretty=format:'%s'", returnStdout: true).trim()
    } catch (Exception e) {
        echo "Warning: Could not retrieve git information: ${e.message}"
    }

    dir("playwright-tests/${subDir}") {
        def sparseCheckout = [[$class: 'SparseCheckoutPaths', sparseCheckoutPaths: [[path: 'docker-compose.yml']]]]
        if (params.branchName =~ /PR-\d+/) {
            def prNumber = (params.branchName =~ /PR-(\d+)/)[0][1]
            checkout([$class: 'GitSCM', branches: [[name: "FETCH_HEAD"]], extensions: [[$class: 'LocalBranch']] + sparseCheckout, userRemoteConfigs: [[refspec: "+refs/pull/${prNumber}/head:refs/remotes/origin/PR-${prNumber}", url: "git@github.com:${params.githubUser}/playwright-tests.git"]]])
        } else {
            checkout([$class: 'GitSCM', branches: [[name: params.branchName]], doGenerateSubmoduleConfigurations: false, extensions: sparseCheckout, submoduleCfg: [], userRemoteConfigs: [[credentialsId: '577cbc72-7d9e-4eba-924c-ecbbe6de9805', url: "git@github.com:${params.githubUser}/playwright-tests.git"]]])
        }

        def credentials = [
            string(credentialsId: 'packagecloud_repo_token', variable: 'PACKAGECLOUD_TOKEN'),
            string(credentialsId: 'github_packages_token', variable: 'GITHUB_TOKEN')
        ]
        def envVariables = [
            "FRAMEWORK_ENV=${params.frameworkEnvironment}",
            "RUNTIME_ENV=${params.runtimeEnvironment}",
            "CONFIG_ENV=${params.configEnvironment}",
            "FRAMEWORK_RUNNER_TAG=${params.frameworkRunnerTag}",
            "TAGS=${params.tags}",
            "GIT_COMMIT_AUTHOR_NAME=${commitAuthor}",
            "GIT_COMMIT_AUTHOR_EMAIL=${commitEmail}",
            "GIT_COMMIT_MESSAGE=${commitMessage}"
        ]
        if (params.reportSuffix) {
            envVariables << "REPORT_SUFFIX=${params.reportSuffix}"
        }
        if (params.envVars && params.envVars.size() > 0) {
            def jsonArray = params.envVars.collect { key, value -> [(key): value.toString()] }
            def jsonString = JsonOutput.toJson(jsonArray)
            envVariables << "ADDITIONAL_ENV_VARS=${jsonString}"
        }
        if (params.pnpmSetupScriptName) {
            envVariables << "PNPM_SETUP_SCRIPT_NAME=${params.pnpmSetupScriptName}"
        }

        def previousBuildResult = currentBuild.previousBuild?.result
        def testsFailed = false

        try {
            withCredentials(credentials) {
                withEcr {
                    withEnv(envVariables) {
                        ansiColor('xterm') {
                            sh """
                                #!/bin/bash -lxe
                                rm -rf test-results
                                rm -rf playwright-reports
                                mkdir playwright-reports
                                chmod -R 777 ./playwright-reports
                                rm -rf playwright-report
                                mkdir playwright-report
                                chmod -R 777 ./playwright-report
                                rm -rf report
                                mkdir report
                                chmod -R 777 ./report
                                docker compose pull framework-runner
                                """
                            withAWS(role: "${params.frameworkEnvironment}-playwright-tests-role", roleAccount: '437795906767',
                            roleSessionName: env.BUILD_TAG, useNode: true) {
                                sh """
                                    #!/bin/bash -lxe
                                    docker compose run --rm framework-runner
                                """
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            testsFailed = true
            throw e
        } finally {
            def reportName = params.reportSuffix ? "Playwright Report - ${params.reportSuffix}" : 'Playwright Report'
            publishHTML(target: [
                allowMissing: false,
                alwaysLinkToLastBuild: true,
                keepAll: true,
                reportDir: 'report',
                reportFiles: 'index.html',
                reportName: reportName
            ])

            def playwrightLink = null
            def datadogLink = null
            try {
                def htmlContent = readFile('report/index.html')
                def matcher = htmlContent =~ /href="([^"]+)"/
                if (matcher.find()) {
                    playwrightLink = matcher.group(1)
                }
                if (matcher.find()) {
                    datadogLink = matcher.group(1)
                }
            } catch (Exception e) {
                echo "Could not extract Playwright link, the report file may be missing."
            }

            def defaultChannel = env.CHANGE_ID ? '#playwright-tests-e2e-results' : '#e2e-test-results'
            def channels = [defaultChannel] + params.slackNotificationChannels
            def stepName = params.reportSuffix ? "Playwright Tests - ${params.reportSuffix}" : 'Playwright Tests'
            def sendSlackMessage = null
            def message = null
            def successOrFailure = testsFailed ? 'FAILURE' : 'SUCCESS'
            def color = 'danger'

            if (testsFailed && params.configEnvironment == 'prod'){
                sendSlackMessage = true
            } else if (testsFailed && (previousBuildResult == 'SUCCESS' || previousBuildResult == null)) {
                sendSlackMessage = true
            } else if (!testsFailed && (previousBuildResult != 'SUCCESS' && previousBuildResult != null)) {
                sendSlackMessage = true
                color = 'good'
            }

            if (sendSlackMessage) {
                def buildDuration = Util.getTimeSpanString(System.currentTimeMillis() - currentBuild.startTimeInMillis)
                message = "${env.JOB_NAME} - #${env.BUILD_NUMBER} (${stepName}) ${successOrFailure} after ${buildDuration} (<${env.BUILD_URL}|Open Jenkins>)"
                if (playwrightLink) {
                    message += " | (<${playwrightLink}|Open Playwright Report>)"
                } else {
                    message += " | (Playwright Report not available)"
                }
                if (datadogLink) {
                    message += " | (<${datadogLink}|Open Datadog>)"
                }
                channels.each { channel ->
                    slackNotify(
                        channel: channel,
                        message: message,
                        color: color
                    )
                }
            }

            if (params.githubPRRepo && params.githubPRID) {
                def ghComment = "**${stepName}: ${successOrFailure}**\\n" +
                                "Tags: `${params.tags}`\\n" +
                                "Pipeline: [#${env.BUILD_NUMBER}](${env.BUILD_URL})\\n"
                if (playwrightLink) {
                    ghComment += "Playwright Report: [Open](${playwrightLink})\\n"
                }

                if (datadogLink) {
                    ghComment += "Datadog Test Run: [Open](${datadogLink})\\n"
                }
                githubPostPrComment(repo: params.githubPRRepo, pullRequestId: params.githubPRID, message: ghComment)
            }
        }
    }
}
