package com.sonymusic

import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test

import static org.hamcrest.CoreMatchers.not
import static org.hamcrest.MatcherAssert.assertThat
import static org.hamcrest.core.StringContains.containsString
import static org.junit.jupiter.api.Assertions.assertNull

class DockerRunTest extends BaseGlobalVarTest {
    def dockerRun

    @BeforeEach
    void setUp() {
        super.setUp()
        dockerRun = loadScript('vars/dockerRun.groovy')
        helper.registerAllowedMethod('sh')
        helper.registerAllowedMethod('withEcr', [Closure])
        binding.setVariable('env', [:])
    }

    @Test
    void testCallWithMissingParameters() {
        assertThrowsWithMessage(
            IllegalArgumentException.class,
            "dockerRun: Missing required parameter: 'script'",
            { dockerRun.call(imageTag: 'test') }
        )

        assertThrowsWithMessage(
            IllegalArgumentException.class,
            "dockerRun: Missing required parameter: 'imageTag'",
            { dockerRun.call(script: 'test') }
        )
    }

    @Test
    void testCallWithImageTag() {
        String script = 'echo hi'

        assertNull(
            dockerRun(script: script, imageTag: 'node18')
        )

        assertMethodCalledTimes('withEcr', 1)

        def arg = assertMethodCalledOnceWith(
            'sh', "086679231553.dkr.ecr.us-east-1.amazonaws.com/docker-parent-images:node18 /bin/bash -c \"${script}\""
        )

        assertThat(arg, not(containsString("--env")))
        assertThat(arg, not(containsString("--user")))
        assertThat(arg, not(containsString("--workdir")))
    }

    @Test
    void testCallWithCustomUser() {
        String user = 'vulture'

        assertNull(
            dockerRun(
                script: 'test',
                imageTag: 'node18',
                user: user
            )
        )

        assertMethodCalledTimes('withEcr', 1)
        assertMethodCalledOnceWith('sh', " --user ${user} ")
    }

    @Test
    void testCallWithCustomWorkdir() {
        String workdir = '/var/lib'

        assertNull(
            dockerRun(
                script: 'test',
                imageTag: 'node18',
                workdir: workdir
            )
        )

        assertMethodCalledTimes('withEcr', 1)
        assertMethodCalledOnceWith('sh', " --workdir ${workdir} ")
    }

    @Test
    void testCallWithCustomImageRepo() {
        String imageRepo = '0000.ecr.test.com/images'
        String imageTag = 'node30'

        assertNull(
            dockerRun(
                script: 'test',
                imageTag: imageTag,
                imageRepo: imageRepo
            )
        )

        assertMethodCalledTimes('withEcr', 1)
        assertMethodCalledOnceWith('sh', " ${imageRepo}:${imageTag} ")
    }
       
    @Test
    void testCallWithEnvVars() {
        def envVars = [
            NODE_VERSION: '20.11.0', 
            TEST: "test's it", 
            QUOTED: "'single'", 
            QUOTED2: '"double"',
            BOOLP: true,
            INTP: 12,
            FOO: 'BAZ',
            VAR_REF: "\${FOO}",
            DOLLAR_VAR: "\$BAR"
        ]

        assertNull(
            dockerRun(
                script: 'test',
                imageTag: 'node18',
                envVars: envVars
            )
        )

        assertMethodCalledTimes('withEcr', 1)
        assertMethodCalledOnceWith('sh', [
            " --env NODE_VERSION='20.11.0' ",
            " --env TEST='test'\"'\"'s it' ",
            " --env QUOTED='single'",
            " --env QUOTED2=\"double\"",
            " --env BOOLP='true'",
            " --env INTP='12'",
            " --env VAR_REF=\${FOO}",
            " --env DOLLAR_VAR=\$BAR",
        ])
    }

    @Test
    void testCallWithVolumes() {
        def volumes = ['./content:/content', 'test:test']

        assertNull(
            dockerRun(
                script: 'test',
                imageTag: 'node18',
                volumes: volumes
            )
        )

        assertMethodCalledTimes('withEcr', 1)
        assertMethodCalledOnceWith('sh', [
            " --volume ./content:/content ",
            " --volume test:test "
        ])
    }

    @Test
    void testIncludesCiEnvVars() {
        binding.setVariable('env', [
            JENKINS_URL: 'workspace-path',
            BUILD_ID: '1234',
            CHANGE_ID: 'pr-1'
        ])

        def envVars = [TEST: 'test']

        assertNull(
            dockerRun(
                script: 'test',
                imageTag: 'node18',
                envVars: envVars
            )
        )

        assertMethodCalledTimes('withEcr', 1)
        assertMethodCalledOnceWith('sh', [
            " --env TEST='test' ",
            " --env JENKINS_URL='workspace-path' ",
            " --env BUILD_ID='1234' ",
            " --env CHANGE_ID='pr-1' "
        ])
    }
}
