package com.sonymusic

import com.lesfurets.jenkins.unit.BasePipelineTest
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test

import static org.hamcrest.CoreMatchers.containsString
import static org.hamcrest.MatcherAssert.assertThat
import static org.junit.jupiter.api.Assertions.*

class FargateDeployTest extends BasePipelineTest {
    def fargateDeploy
    def environment = 'qa'
    def serviceName = 'service'
    def gitCommit = 'dummy'

    @BeforeEach
    void setUp() {
        super.setUp()
        fargateDeploy = loadScript("vars/fargateDeploy.groovy")
        helper.registerAllowedMethod('sh')
        helper.registerAllowedMethod('withEcr', [Closure])
    }

    @Test
    void testCallWithNoArgs() {
        // Assert error is thrown since required args are not supplied
        assertThrows(AssertionError.class, {
            fargateDeploy.call(dummy: 'dummy')
        })
    }

    @Test
    void testCallWithBadRegion() {
        // Assert error is thrown since awsRegions is a string
        assertThrows(AssertionError.class, {
            fargateDeploy.call(
                environment: environment,
                awsRegions: 'dummy',
                serviceName: serviceName,
                gitCommit: gitCommit,
            )
        })
    }

    @Test
    void testCallWithBadDeployType() {
        assertThrows(AssertionError.class, {
            fargateDeploy.call(
                environment: environment,
                awsRegions: ['dummy'],
                serviceName: serviceName,
                gitCommit: gitCommit,
                deployType: 'INVALID'
            )
        })
    }

    @Test
    void testCallWithSuccess() {
        // This one should succeed and return nothing
        assertNull(fargateDeploy(
            environment: environment,
            awsRegions: ['dummy'],
            serviceName: serviceName,
            gitCommit: gitCommit,
            customSidecars: ['s1', 's2'],
            doUpdateCustomSidecars: true,
        ))

        // Do a simple test that the previous method call made it to the shell block
        assertEquals(1, helper.callStack.findAll{ it.methodName == 'sh' }.size())

        // Test that the environment variables are passed to the shell command correctly
        def withEnv = [
            "AWS_REGION=dummy",
            "CLUSTER_NAME=${environment}-${serviceName}",
            "CONTAINER_NAME=${serviceName}",
            "CUSTOM_SIDECARS=s1,s2",
            "DO_UPDATE_CUSTOM_SIDECARS=true",
            "Environment=${environment}",
            "FARGATE_SERVICE_NAME=${environment}-${serviceName}",
            "GIT_COMMIT=${gitCommit}",
            "SERVICE_NAME=${serviceName}",
            "TASK_FAMILY=${environment}-${serviceName}",
            "OUTPUT_FILE_PATH=/var/app/task_details.json",
        ]

        // Get the actual 'sh' command from the call stack
        def shArgs = helper.callStack.findAll { it.methodName == 'sh' }[0].argsToString()

        // Check that each expected environment variable is in the 'sh' command
        withEnv.each { envVar ->
            assertThat(shArgs, containsString("-e '${envVar}'"))
        }

        assertThat(shArgs, containsString('deploy'))
    }

    @Test
    void testCallWithOptionalArgs() {
        assertNull(fargateDeploy(
            environment: environment,
            awsRegions: ['dummy'],
            serviceName: serviceName,
            gitCommit: gitCommit,
            deployMode: 'test',
            deployType: 'UPDATE_CLOUDWATCH_EVENT',
            ecrRegistryAccountId: '123456789012',
            ecrRegistryRegion: 'us-west-2',
            forceScaleOut: true,
            imageNameOverride: 'some-image',
            updateTimeout: 600,
        ))

        // Do a simple test that the previous method call made it to the shell block
        assertEquals(1, helper.callStack.findAll{ it.methodName == 'sh' }.size())

        // Test that the environment variables are passed to the shell command correctly
        def withEnv = [
            "AWS_REGION=dummy",
            "CLUSTER_NAME=${environment}-${serviceName}",
            "CONTAINER_NAME=${serviceName}",
            "CUSTOM_SIDECARS=",
            "DO_UPDATE_CUSTOM_SIDECARS=false",
            "Environment=${environment}",
            "FARGATE_SERVICE_NAME=${environment}-${serviceName}",
            "GIT_COMMIT=${gitCommit}",
            "SERVICE_NAME=${serviceName}",
            "TASK_FAMILY=${environment}-${serviceName}",
            "OUTPUT_FILE_PATH=/var/app/task_details.json",
            "DEPLOY_MODE=test",
            "ECR_REGISTRY_ACCOUNT_ID=123456789012",
            "ECR_REGISTRY_REGION=us-west-2",
            "FORCE_SCALE_OUT=true",
            "IMAGE_NAME_OVERRIDE=some-image",
            "UPDATE_TIMEOUT=600",
        ]
        def shArgs = helper.callStack.findAll{ it.methodName == 'sh' }[0].argsToString()
        withEnv.each { envVar ->
            assertThat(shArgs, containsString("-e '${envVar}'"))
        }
        assertThat(shArgs, containsString('update-cloudwatch-event'))
    }
}
