// Copyright © 2024. Citrix Systems, Inc.

package test

import (
	"context"
	"fmt"
	"os"
	"strconv"
	"strings"
	"testing"

	"github.com/citrix/terraform-provider-citrix/internal/util"
	"github.com/hashicorp/terraform-plugin-framework/diag"
	"github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

// testHypervisorPreCheck validates the necessary env variable exist
// in the testing environment
func TestAzureMcsSuitePreCheck(t *testing.T) {
	ctx := context.Background()
	client := sharedClientForSweepers(ctx)

	diag := diag.Diagnostics{}

	isDDCVersionSupportedForCatalogAndDelGrp := util.CheckProductVersion(client, &diag, 120, 120, 7, 42, "", "")

	isDDCVersionSupportedForPolicy := util.CheckProductVersion(client, &diag, 120, 118, 7, 41, "", "")
	customerId := os.Getenv("CITRIX_CUSTOMER_ID")
	isOnPremises := true
	if customerId != "" && customerId != "CitrixOnPremises" {
		// Tests being run in cloud env
		isOnPremises = false
	}
	isPre2407AndOnPremises := false
	if isOnPremises && !isDDCVersionSupportedForCatalogAndDelGrp {
		// Tests being run in on-premises environment with CVAD version < 2407
		isPre2407AndOnPremises = true
	}

	TestProviderPreCheck(t)
	TestHypervisorPreCheck_Azure(t)
	TestHypervisorResourcePoolPreCheck_Azure(t)

	if !isPre2407AndOnPremises {
		TestServiceAccountPreCheck_AD(t)
	}
	TestMachineCatalogPreCheck_Azure(t)
	TestMachineCatalogPreCheck_Manual_Power_Managed_Azure(t)
	TestDesktopIconPreCheck(t)
	TestDeliveryGroupPreCheck(t)
	TestAdminFolderPreCheck(t)
	TestApplicationResourcePreCheck(t)
	TestAdminScopeResourcePreCheck(t)
	TestAdminRolePreCheck(t)
	if isDDCVersionSupportedForPolicy {
		TestPolicySetResourcePreCheck(t)
	}

	if !isOnPremises {
		TestAzureImageDefinitionResourcePreCheckForTestSuite(t)
		TestMachineCatalogPreCheck_AzureAd(t)
		TestMachineCatalogPreCheck_Workgroup(t)
	} else {
		TestAdminUserPreCheck(t)
	}
}

func TestAzureMcs(t *testing.T) {
	ctx := context.Background()
	client := sharedClientForSweepers(ctx)
	diag := diag.Diagnostics{}
	isDDCVersionSupportedForPolicy := util.CheckProductVersion(client, &diag, 120, 118, 7, 41, "", "")

	isDDCVersionSupportedForCatalogAndDelGrp := util.CheckProductVersion(client, &diag, 120, 120, 7, 42, "", "")

	customerId := os.Getenv("CITRIX_CUSTOMER_ID")
	isOnPremises := true
	if customerId != "" && customerId != "CitrixOnPremises" {
		// Tests being run in cloud env
		isOnPremises = false
	}
	isPre2407AndOnPremises := false
	if isOnPremises && !isDDCVersionSupportedForCatalogAndDelGrp {
		// Tests being run in on-premises environment with CVAD version < 2407
		isPre2407AndOnPremises = true
	}
	gotestContext := os.Getenv("GOTEST_CONTEXT")
	isGitHubAction := false
	if gotestContext != "" && gotestContext == "github" {
		// Tests being run in GitHub Action
		isGitHubAction = true
	}

	zoneInput := os.Getenv("TEST_ZONE_INPUT_AZURE")
	zoneDescription := os.Getenv("TEST_ZONE_DESCRIPTION")
	if zoneInput == "" {
		zoneInput = "second zone"
		zoneDescription = "description for go test zone"
	}

	hypervName := os.Getenv("TEST_HYPERV_NAME_AZURE")
	resourcePoolName := os.Getenv("TEST_HYPERV_RP_NAME")
	machineCatalogName := os.Getenv("TEST_MC_NAME")
	deliveryGroupName := os.Getenv("TEST_DG_NAME")
	hybridCatalogName := machineCatalogName + "-HybAAD"
	aadCatalogName := machineCatalogName + "-AAD"
	workgroupCatalogName := machineCatalogName + "-WRKGRP"
	manualPmCatalogName := os.Getenv("TEST_MC_NAME_MANUAL")
	applicationName := os.Getenv("TEST_APP_NAME")
	appFolderName := os.Getenv("TEST_ADMIN_FOLDER_NAME")
	folder_name_1 := fmt.Sprintf("%s-1", appFolderName)
	folder_name_1_updated := fmt.Sprintf("%s-1-updated", appFolderName)
	folder_name_2 := fmt.Sprintf("%s-2", appFolderName)
	adminScopeName := os.Getenv("TEST_ADMIN_SCOPE_NAME")
	adminRoleName := os.Getenv("TEST_ROLE_NAME")
	userName := os.Getenv("TEST_ADMIN_USER_NAME")
	userDomainName := os.Getenv("TEST_ADMIN_USER_DOMAIN")

	resource.Test(t, resource.TestCase{
		ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
		PreCheck: func() {
			TestProviderPreCheck(t)
			TestHypervisorPreCheck_Azure(t)
			TestHypervisorResourcePoolPreCheck_Azure(t)
			if !isPre2407AndOnPremises {
				TestServiceAccountPreCheck_AD(t)
			}
			TestMachineCatalogPreCheck_Azure(t)
			TestMachineCatalogPreCheck_Manual_Power_Managed_Azure(t)
			TestDesktopIconPreCheck(t)
			TestDeliveryGroupPreCheck(t)
			TestAdminFolderPreCheck(t)
			TestApplicationResourcePreCheck(t)
			if isDDCVersionSupportedForPolicy {
				TestPolicySetResourcePreCheck(t)
			}
		},
		Steps: []resource.TestStep{
			/****************** Zone Test ******************/
			// Zone - Create and Read testing
			{
				Config: BuildZoneResource(t, zoneInput, false),
				Check:  getAggregateTestFunc(isOnPremises, zoneInput, zoneDescription),
			},
			// ImportState testing
			{
				ResourceName:      "citrix_zone.test",
				ImportState:       true,
				ImportStateVerify: true,
				// The last_updated attribute does not exist in the Orchestration
				// API, therefore there is no value for it during import.
				ImportStateVerifyIgnore: []string{"last_updated", "metadata"},
			},
			// Update and Read testing
			{
				Config: BuildZoneResource(t, zoneInput, true),
				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify name of zone
					resource.TestCheckResourceAttr("citrix_zone.test", "name", fmt.Sprintf("%s-updated", zoneInput)),
					// Verify description of zone
					resource.TestCheckResourceAttr("citrix_zone.test", "description", fmt.Sprintf("updated %s", zoneDescription)),
					// Verify number of meta data of zone
					resource.TestCheckResourceAttr("citrix_zone.test", "metadata.#", "4"),
					// Verify first meta data value
					resource.TestCheckResourceAttr("citrix_zone.test", "metadata.3.name", "key4"),
					resource.TestCheckResourceAttr("citrix_zone.test", "metadata.3.value", "value4"),
				),
				SkipFunc: skipForCloud(isOnPremises),
			},

			/****************** Hypervisor Test ******************/
			// Create and Read testing
			{
				Config: composeTestResourceTf(
					BuildHypervisorResourceAzure(t, hypervisor_testResources),
					BuildZoneResource(t, zoneInput, true),
				),

				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify name of hypervisor
					resource.TestCheckResourceAttr("citrix_azure_hypervisor.testHypervisor", "name", hypervName),
					resource.TestCheckResourceAttr("citrix_azure_hypervisor.testHypervisor", "metadata.#", "3"),
				),
			},
			// ImportState testing
			{
				ResourceName:      "citrix_azure_hypervisor.testHypervisor",
				ImportState:       true,
				ImportStateVerify: true,
				// The last_updated attribute does not exist in the Orchestration
				// API, therefore there is no value for it during import.
				ImportStateVerifyIgnore: []string{"application_secret", "metadata"},
			},
			// Update and Read testing
			{
				Config: composeTestResourceTf(
					BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
					BuildZoneResource(t, zoneInput, true),
				),
				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify name of hypervisor
					resource.TestCheckResourceAttr("citrix_azure_hypervisor.testHypervisor", "name", fmt.Sprintf("%s-updated", hypervName)),
					resource.TestCheckResourceAttr("citrix_azure_hypervisor.testHypervisor", "metadata.#", "4"),
				),
			},

			/****************** Resource Pool Test ******************/
			// Create and Read testing
			{
				Config: composeTestResourceTf(
					BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_testResource_azure),
					BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
					BuildZoneResource(t, zoneInput, true),
				),

				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr("citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool", "name", resourcePoolName),
					// Verify name of virtual network resource group name
					resource.TestCheckResourceAttr("citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool", "virtual_network_resource_group", os.Getenv("TEST_HYPERV_RP_VIRTUAL_NETWORK_RESOURCE_GROUP")),
					// Verify name of virtual network
					resource.TestCheckResourceAttr("citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool", "virtual_network", os.Getenv("TEST_HYPERV_RP_VIRTUAL_NETWORK")),
					// Verify name of the region
					resource.TestCheckResourceAttr("citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool", "region", os.Getenv("TEST_HYPERV_RP_REGION")),
					// Verify subnets
					resource.TestCheckResourceAttr("citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool", "subnets.#", strconv.Itoa(len(strings.Split(os.Getenv("Test_HYPERV_RP_SUBNETS"), ",")))),
				),
			},
			// ImportState testing
			{
				ResourceName:      "citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool",
				ImportState:       true,
				ImportStateIdFunc: generateImportStateId,
				ImportStateVerify: true,
			},
			// Update and Read
			{
				Config: composeTestResourceTf(
					BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
					BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
					BuildZoneResource(t, zoneInput, true),
				),
				Check: resource.ComposeAggregateTestCheckFunc(
					resource.TestCheckResourceAttr("citrix_azure_hypervisor_resource_pool.testHypervisorResourcePool", "name", fmt.Sprintf("%s-updated", resourcePoolName)),
				),
			},

			/*******************Image Definition Test******************/
			{
				Config: composeTestResourceTf(
					BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
					BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
					BuildZoneResource(t, zoneInput, true),
					BuildAzureImageDefinitionTestResourceForTestSuite(t),
				),
				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify the name of the image definition
					resource.TestCheckResourceAttr("citrix_image_definition.test_azure_image_definition", "name", os.Getenv("TEST_IMAGE_DEFINITION_NAME")),
					// Verify the description of the image definition
					resource.TestCheckResourceAttr("citrix_image_definition.test_azure_image_definition", "description", os.Getenv("TEST_IMAGE_DEFINITION_DESCRIPTION")),
					// Verify the os_type of the image definition
					resource.TestCheckResourceAttr("citrix_image_definition.test_azure_image_definition", "os_type", os.Getenv("TEST_IMAGE_DEFINITION_OS_TYPE")),
					// Verify the session_support of the image definition
					resource.TestCheckResourceAttr("citrix_image_definition.test_azure_image_definition", "session_support", os.Getenv("TEST_IMAGE_DEFINITION_SESSION_SUPPORT")),
				),
				SkipFunc: skipForOnPrem(isOnPremises),
			},
			// Import testing
			{
				ResourceName:            "citrix_image_definition.test_azure_image_definition",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"hypervisor"},
				SkipFunc:                skipForOnPrem(isOnPremises),
			},
			// Update and Read testing
			{
				Config: composeTestResourceTf(
					BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
					BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
					BuildZoneResource(t, zoneInput, true),
					BuildAzureImageDefinitionUpdatedTestResourceForTestSuite(t),
				),
				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify the name of the image definition
					resource.TestCheckResourceAttr("citrix_image_definition.test_azure_image_definition", "name", os.Getenv("TEST_IMAGE_DEFINITION_NAME_UPDATED")),
					// Verify the description of the image definition
					resource.TestCheckResourceAttr("citrix_image_definition.test_azure_image_definition", "description", os.Getenv("TEST_IMAGE_DEFINITION_DESCRIPTION_UPDATED")),
					// Verify the os_type of the image definition
					resource.TestCheckResourceAttr("citrix_image_definition.test_azure_image_definition", "os_type", os.Getenv("TEST_IMAGE_DEFINITION_OS_TYPE_UPDATED")),
					// Verify the session_support of the image definition
					resource.TestCheckResourceAttr("citrix_image_definition.test_azure_image_definition", "session_support", os.Getenv("TEST_IMAGE_DEFINITION_SESSION_SUPPORT_UPDATED")),
				),
				SkipFunc: skipForOnPrem(isOnPremises),
			},

			/*******************Service Account Test*******************/
			// Create and Read testing
			{
				Config: composeTestResourceTf(
					BuildServiceAccountResourceAD(t, testServiceAccountResourceAD),
				),
				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify name of hypervisor
					resource.TestCheckResourceAttr("citrix_service_account.testServiceAccountAD", "display_name", os.Getenv("TEST_SERVICE_ACCOUNT_DISPLAY_NAME")),
					resource.TestCheckResourceAttr("citrix_service_account.testServiceAccountAD", "identity_provider_identifier", os.Getenv("TEST_SERVICE_ACCOUNT_AD_DOMAIN_NAME")),
				),
				SkipFunc: skipForCVADVersion(isPre2407AndOnPremises),
			},
			// Import testing
			{
				ResourceName:      "citrix_service_account.testServiceAccountAD",
				ImportState:       true,
				ImportStateVerify: true,
				// The last_updated attribute does not exist in the Orchestration
				// API, therefore there is no value for it during import.
				ImportStateVerifyIgnore: []string{"account_secret", "account_secret_format"},
				SkipFunc:                skipForCVADVersion(isPre2407AndOnPremises),
			},
			// Update and Read
			{
				Config: composeTestResourceTf(BuildServiceAccountResourceAD(t, testServiceAccountResourceAD_updated)),
				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify name of hypervisor
					resource.TestCheckResourceAttr("citrix_service_account.testServiceAccountAD", "display_name", fmt.Sprintf("%s-updated", os.Getenv("TEST_SERVICE_ACCOUNT_DISPLAY_NAME"))),
				),
				SkipFunc: skipForCVADVersion(isPre2407AndOnPremises),
			},

			/****************** Machine Catalog Test - MCS AD / AAD / HybridAAD - Manual Power Managed ******************/
			// Create and Read testing
			{
				Config: composeAzureMachineCatalogTestResourceTf(t, isOnPremises, isPre2407AndOnPremises),
				Check: func() resource.TestCheckFunc {
					checks := []resource.TestCheckFunc{
						/*** Verify MCS AD Machine Catalog ***/
						// Verify name of catalog
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", machineCatalogName),
						// Verify domain FQDN
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "session_support", "MultiSession"),
						// Verify machine catalog identity type
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.identity_type", "ActiveDirectory"),
						// Verify nic network
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.network_mapping.0.network", os.Getenv("TEST_MC_SUBNET")),

						/*** Verify MCS Hybrid AAD Machine Catalog ***/
						// Verify name of catalog
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "name", hybridCatalogName),
						// Verify domain FQDN
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "session_support", "MultiSession"),
						// Verify machine catalog identity type
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "provisioning_scheme.identity_type", "HybridAzureAD"),
						// Verify nic network
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-HybAAD", "provisioning_scheme.network_mapping.0.network", os.Getenv("TEST_MC_SUBNET")),

						/*** Optional - Verify MCS AAD / WorkGroup Machine Catalog ***/
						composeCloudMachineCatalogTestVerification(isOnPremises, aadCatalogName, workgroupCatalogName),

						/*** Verify Manual Power Managed Machine Catalog ***/
						// Verify name of catalog
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogManualPowerManaged", "name", manualPmCatalogName),
						// Verify session support
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogManualPowerManaged", "session_support", os.Getenv("TEST_MC_SESSION_SUPPORT_MANUAL_POWER_MANAGED")),
						// Verify total number of machines
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogManualPowerManaged", "machine_accounts.#", "1"),
					}

					// Only test Zero Machine Catalog if not pre-2407 and on-premises
					if !isPre2407AndOnPremises {
						zeroMachineChecks := []resource.TestCheckFunc{
							/***Verify Machine Catalog with Zero Machine Count***/
							// Verify name of catalog
							resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogMachines", "name", "ZeroMachinesCatalog"),
							// Verify total number of machines
							resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogMachines", "provisioning_scheme.number_of_total_machines", "0"),
						}
						checks = append(checks, zeroMachineChecks...)
					}
					return resource.ComposeAggregateTestCheckFunc(checks...)
				}(),
			},
			// ImportState testing - MCS AD
			{
				ResourceName:      "citrix_machine_catalog.testMachineCatalog",
				ImportState:       true,
				ImportStateVerify: true,
				// The last_updated attribute does not exist in the Orchestration
				// API, therefore there is no value for it during import.
				ImportStateVerifyIgnore: []string{"provisioning_scheme.network_mapping", "provisioning_scheme.azure_machine_config.writeback_cache", "provisioning_scheme.machine_domain_identity.service_account", "provisioning_scheme.machine_config.service_account_password", "delete_machine_accounts", "force_delete"},
				SkipFunc:                skipForGitHubAction(isGitHubAction),
			},
			// ImportState testing - MCS HybridAAD
			{
				ResourceName:      "citrix_machine_catalog.testMachineCatalog-HybAAD",
				ImportState:       true,
				ImportStateVerify: true,
				// The last_updated attribute does not exist in the Orchestration
				// API, therefore there is no value for it during import.
				ImportStateVerifyIgnore: []string{"provisioning_scheme.network_mapping", "provisioning_scheme.azure_machine_config.writeback_cache", "provisioning_scheme.machine_domain_identity.service_account", "provisioning_scheme.machine_config.service_account_password", "delete_machine_accounts", "force_delete"},
				SkipFunc:                skipForGitHubAction(isGitHubAction),
			},
			// ImportState testing - MCS AAD
			{
				ResourceName:      "citrix_machine_catalog.testMachineCatalog-AAD",
				ImportState:       true,
				ImportStateVerify: true,
				// The last_updated attribute does not exist in the Orchestration
				// API, therefore there is no value for it during import.
				ImportStateVerifyIgnore: []string{"provisioning_scheme.network_mapping", "provisioning_scheme.azure_machine_config.writeback_cache", "delete_machine_accounts", "force_delete"},
				SkipFunc:                func() (bool, error) { return (isOnPremises || isGitHubAction), nil },
			},
			// ImportState testing
			{
				ResourceName:      "citrix_machine_catalog.testMachineCatalog-WG",
				ImportState:       true,
				ImportStateVerify: true,
				// The last_updated attribute does not exist in the Orchestration
				// API, therefore there is no value for it during import.
				ImportStateVerifyIgnore: []string{"provisioning_scheme.network_mapping", "provisioning_scheme.azure_machine_config.writeback_cache", "delete_machine_accounts", "force_delete"},
				SkipFunc:                func() (bool, error) { return (isOnPremises || isGitHubAction), nil },
			},
			// ImportState testing - Manual Power Managed
			{
				ResourceName:            "citrix_machine_catalog.testMachineCatalogManualPowerManaged",
				ImportState:             true,
				ImportStateVerify:       true,
				ImportStateVerifyIgnore: []string{"machine_accounts", "is_remote_pc", "is_power_managed", "delete_machine_accounts", "force_delete"},
			},

			/****************** Delivery Group Test - Create ******************/
			// Create and Read testing
			{
				Config: func() string {
					resources := []string{
						BuildDeliveryGroupResource(t, testDeliveryGroupResources, "DesktopsAndApps"),
					}
					if !isPre2407AndOnPremises {
						resources = append(resources,
							BuildDeliveryGroupResourceWithZeroCatalogs(t, testDeliveryGroupWithZeroCatalogs),
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure, "", "ActiveDirectory"),
							BuildServiceAccountResourceAD(t, testServiceAccountResourceAD_updated),
						)
					} else {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_without_serv_acc_uid, "", "ActiveDirectory"),
						)
					}
					resources = append(resources,
						BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
						BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
						BuildZoneResource(t, zoneInput, true),
					)
					return composeTestResourceTf(resources...)
				}(),

				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify name of delivery group
					resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "name", deliveryGroupName),
					// Verify description of delivery group
					resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "description", "Delivery Group for testing"),
					// Verify delivery type of delivery group
					resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "delivery_type", "DesktopsAndApps"),
					// Verify number of desktops
					resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "desktops.#", "2"),
					// Verify number of reboot schedules
					resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "reboot_schedules.#", "2"),
					// Verify total number of machines in delivery group
					resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "total_machines", "1"),
				),
			},
			// ImportState testing
			{
				ResourceName:      "citrix_delivery_group.testDeliveryGroup",
				ImportState:       true,
				ImportStateVerify: true,
				// The last_updated attribute does not exist in the Orchestration
				// API, therefore there is no value for it during import.
				ImportStateVerifyIgnore: []string{"last_updated", "autoscale_settings", "associated_machine_catalogs", "reboot_schedules", "delivery_type", "delete_machine_accounts", "force_delete"},
				SkipFunc:                skipForGitHubAction(isGitHubAction),
			},

			/****************** Delivery Group Test - MCS AD - Update ******************/
			// Machine Catalog: Update description, master image and add machine test
			// Delivery Group: Update name, description and add machine testing
			{
				Config: func() string {
					resources := []string{

						BuildDeliveryGroupResource(t, testDeliveryGroupResources_updated, "DesktopsAndApps"),
					}
					if !isPre2407AndOnPremises {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_updated, "", "ActiveDirectory"),
							BuildDeliveryGroupResourceWithZeroCatalogs(t, testDeliveryGroupWithZeroCatalogsUpdated),
							BuildMachineCatalogWithZeroMachines(t, machinecatalog_testResources_zeroMachines_azureUpdated),
							BuildServiceAccountResourceAD(t, testServiceAccountResourceAD_updated))
					} else {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_without_serv_acc_updated, "", "ActiveDirectory"),
						)
					}
					resources = append(resources,
						BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
						BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
						BuildZoneResource(t, zoneInput, true),
					)
					return composeTestResourceTf(resources...)
				}(),
				Check: func() resource.TestCheckFunc {
					checks := []resource.TestCheckFunc{
						/*** Verify Machine Catalog ***/
						// Verify updated name of catalog
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", machineCatalogName),
						// Verify updated description
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "description", "updatedCatalog"),
						// Verify updated image
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.azure_machine_config.azure_master_image.master_image", os.Getenv("TEST_MC_MASTER_IMAGE_UPDATED")),
						// Verify domain admin username
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.machine_domain_identity.service_account", os.Getenv("TEST_MC_SERVICE_ACCOUNT")),
						// Verify machine catalog identity type
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.identity_type", "ActiveDirectory"),
						// Verify total number of machines
						resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.number_of_total_machines", "2"),

						/*** Verify Delivery Group ***/
						// Verify name of delivery group
						resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "name", fmt.Sprintf("%s-updated", deliveryGroupName)),
						// Verify description of delivery group
						resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "description", "Delivery Group for testing updated"),
						// Verify delivery type of delivery group
						resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "delivery_type", "DesktopsAndApps"),
						// Verify number of desktops
						resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "desktops.#", "1"),
						// Verify number of reboot schedules
						resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "reboot_schedules.#", "1"),
						// Verify number of reboot schedules
						resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "reboot_schedules.0.ignore_maintenance_mode", "false"),
						// Verify total number of machines in delivery group
						resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "total_machines", "2"),
					}

					// Only test Updated Machine Count when not pre-2407 and on-premises
					if !isPre2407AndOnPremises {
						updatedMachineChecks := []resource.TestCheckFunc{
							/*** Verify Machine Catalog with Updated Machine Count ***/
							// Verify name of catalog
							resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogMachines", "name", "UpdatedOneMachineCatalog"),
							// Verify total number of machines
							resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalogMachines", "provisioning_scheme.number_of_total_machines", "1"),

							/*** Verify Delivery Group with Updated Machine Count ***/
							// Verify name of delivery group
							resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroupZeroCatalogs", "name", "DeliveryGroupWithAssociatedCatalogs"),
							// Verify the presence of an associated machine catalog
							resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroupZeroCatalogs", "associated_machine_catalogs.#", "1"),
							// Verify machine count in the associated machine catalog
							resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroupZeroCatalogs", "associated_machine_catalogs.0.machine_count", "1"),
						}
						checks = append(checks, updatedMachineChecks...)
					}

					return resource.ComposeAggregateTestCheckFunc(checks...)
				}(),
			},

			/****************** Machine Catalog & Delivery Group Test - MCS AD - Delete Machine ******************/
			// Delivery Group: Remove machine test
			// Machine Catalog: Delete machine test
			{
				Config: func() string {
					resources := []string{
						BuildDeliveryGroupResource(t, testDeliveryGroupResources, "DesktopsAndApps"),
					}
					if !isPre2407AndOnPremises {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
							BuildServiceAccountResourceAD(t, testServiceAccountResourceAD_updated))
					} else {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_without_serv_acc_uid_delete_machine, "", "ActiveDirectory"),
						)
					}
					resources = append(resources,
						BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
						BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
						BuildZoneResource(t, zoneInput, true),
					)
					return composeTestResourceTf(resources...)
				}(),
				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify total number of machines in delivery group
					resource.TestCheckResourceAttr("citrix_delivery_group.testDeliveryGroup", "total_machines", "1"),
					// Verify updated name of catalog
					resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "name", machineCatalogName),
					// Verify total number of machines
					resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.number_of_total_machines", "1"),
					// Verify machine catalog identity type
					resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog", "provisioning_scheme.identity_type", "ActiveDirectory"),
				),
			},

			/****************** Admin Folder Test ******************/
			// Create and Read testing
			{
				Config: func() string {
					resources := []string{
						BuildAdminFolderResource(t, testAdminFolderResource, "ContainsApplications"),
						BuildDeliveryGroupResource(t, testDeliveryGroupResources, "DesktopsAndApps"),
					}
					if !isPre2407AndOnPremises {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
							BuildServiceAccountResourceAD(t, testServiceAccountResourceAD_updated))
					} else {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_without_serv_acc_uid_delete_machine, "", "ActiveDirectory"),
						)
					}
					resources = append(resources,
						BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
						BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
						BuildZoneResource(t, zoneInput, true),
					)
					return composeTestResourceTf(resources...)
				}(),
				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify name of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder1", "name", folder_name_1),
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "name", folder_name_2),
					// Verify parent path of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "parent_path", folder_name_1),
					// Verify path of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder1", "path", folder_name_1),
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "path", fmt.Sprintf("%s\\%s", folder_name_1, folder_name_2)),
					// Verify type of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder1", "type.#", "1"),
					resource.TestCheckTypeSetElemAttr("citrix_admin_folder.testAdminFolder1", "type.*", "ContainsApplications"),
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "type.#", "1"),
					resource.TestCheckTypeSetElemAttr("citrix_admin_folder.testAdminFolder2", "type.*", "ContainsApplications"),
				),
			},
			// ImportState testing
			{
				ResourceName:      "citrix_admin_folder.testAdminFolder2",
				ImportState:       true,
				ImportStateVerify: true,
			},
			// Update type testing
			{
				Config: func() string {
					resources := []string{
						BuildAdminFolderResource(t, testAdminFolderResource, "ContainsApplicationGroups"),
						BuildDeliveryGroupResource(t, testDeliveryGroupResources, "DesktopsAndApps"),
					}
					if !isPre2407AndOnPremises {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
							BuildServiceAccountResourceAD(t, testServiceAccountResourceAD_updated))
					} else {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_without_serv_acc_uid_delete_machine, "", "ActiveDirectory"),
						)
					}
					resources = append(resources,
						BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
						BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
						BuildZoneResource(t, zoneInput, true),
					)
					return composeTestResourceTf(resources...)
				}(),
				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify name of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder1", "name", folder_name_1),
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "name", folder_name_2),
					// Verify parent path of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "parent_path", folder_name_1),
					// Verify path of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder1", "path", folder_name_1),
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "path", fmt.Sprintf("%s\\%s", folder_name_1, folder_name_2)),
					// Verify type of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder1", "type.#", "1"),
					resource.TestCheckTypeSetElemAttr("citrix_admin_folder.testAdminFolder1", "type.*", "ContainsApplicationGroups"),
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "type.#", "1"),
					resource.TestCheckTypeSetElemAttr("citrix_admin_folder.testAdminFolder2", "type.*", "ContainsApplicationGroups"),
				),
			},
			// Update name and parent path testing
			{
				Config: func() string {
					resources := []string{
						BuildAdminFolderResource(t, testAdminFolderResource_nameAndParentPathUpdated1, "ContainsApplications"),
						BuildDeliveryGroupResource(t, testDeliveryGroupResources, "DesktopsAndApps"),
					}
					if !isPre2407AndOnPremises {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
							BuildServiceAccountResourceAD(t, testServiceAccountResourceAD_updated))
					} else {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_without_serv_acc_uid_delete_machine, "", "ActiveDirectory"),
						)
					}
					resources = append(resources,
						BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
						BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
						BuildZoneResource(t, zoneInput, true),
					)
					return composeTestResourceTf(resources...)
				}(),
				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify name of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder1", "name", folder_name_1_updated),
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "name", folder_name_2),
					// Verify parent path of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "parent_path", folder_name_1_updated),
					// Verify path of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder1", "path", folder_name_1_updated),
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "path", fmt.Sprintf("%s\\%s", folder_name_1_updated, folder_name_2)),
					// Verify type of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder1", "type.#", "1"),
					resource.TestCheckTypeSetElemAttr("citrix_admin_folder.testAdminFolder1", "type.*", "ContainsApplications"),
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "type.#", "1"),
					resource.TestCheckTypeSetElemAttr("citrix_admin_folder.testAdminFolder2", "type.*", "ContainsApplications"),
				),
			},
			// Update name and remove parent path testing
			{
				Config: func() string {
					resources := []string{
						BuildAdminFolderResource(t, testAdminFolderResource_parentPathRemoved, "ContainsApplications"),
						BuildDeliveryGroupResource(t, testDeliveryGroupResources, "DesktopsAndApps"),
					}
					if !isPre2407AndOnPremises {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
							BuildServiceAccountResourceAD(t, testServiceAccountResourceAD_updated))
					} else {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_without_serv_acc_uid_delete_machine, "", "ActiveDirectory"),
						)
					}
					resources = append(resources,
						BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
						BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
						BuildZoneResource(t, zoneInput, true),
					)
					return composeTestResourceTf(resources...)
				}(),
				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify name of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder1", "name", folder_name_1_updated),
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "name", folder_name_2),
					// Verify path of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder1", "path", folder_name_1_updated),
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "path", folder_name_2),
					// Verify type of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder1", "type.#", "1"),
					resource.TestCheckTypeSetElemAttr("citrix_admin_folder.testAdminFolder1", "type.*", "ContainsApplications"),
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "type.#", "1"),
					resource.TestCheckTypeSetElemAttr("citrix_admin_folder.testAdminFolder2", "type.*", "ContainsApplications"),
				),
			},
			// Update name and remove parent path testing
			{
				Config: func() string {
					resources := []string{
						BuildAdminFolderResourceWithTwoTypes(t, testAdminFolderResource_twoTypes, "ContainsMachineCatalogs", "ContainsApplications"),
						BuildDeliveryGroupResource(t, testDeliveryGroupResources, "DesktopsAndApps"),
					}
					if !isPre2407AndOnPremises {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
							BuildServiceAccountResourceAD(t, testServiceAccountResourceAD_updated))
					} else {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_without_serv_acc_uid_delete_machine, "", "ActiveDirectory"),
						)
					}
					resources = append(resources,
						BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
						BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
						BuildZoneResource(t, zoneInput, true),
					)
					return composeTestResourceTf(resources...)
				}(),
				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify name of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder1", "name", folder_name_1_updated),
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "name", folder_name_2),
					// Verify path of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder1", "path", folder_name_1_updated),
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "path", folder_name_2),
					// Verify type of admin folder
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder1", "type.#", "2"),
					resource.TestCheckTypeSetElemAttr("citrix_admin_folder.testAdminFolder1", "type.*", "ContainsMachineCatalogs"),
					resource.TestCheckTypeSetElemAttr("citrix_admin_folder.testAdminFolder1", "type.*", "ContainsApplications"),
					resource.TestCheckResourceAttr("citrix_admin_folder.testAdminFolder2", "type.#", "2"),
					resource.TestCheckTypeSetElemAttr("citrix_admin_folder.testAdminFolder2", "type.*", "ContainsMachineCatalogs"),
					resource.TestCheckTypeSetElemAttr("citrix_admin_folder.testAdminFolder2", "type.*", "ContainsApplications"),
				),
			},

			/****************** Application Test / Policy Test / Admin Scope / Admin Role Test - In Parallel ******************/
			// Create and Read testing
			{
				Config: func() string {
					resources := []string{
						BuildAdminRoleResource(t, adminRoleTestResource),
						BuildAdminScopeResource(t, adminScopeTestResource),

						BuildApplicationResource(t, testApplicationResource),
						BuildAdminFolderResourceWithTwoTypes(t, testAdminFolderResource_twoTypes, "ContainsMachineCatalogs", "ContainsApplications"),
						BuildDeliveryGroupResource(t, testDeliveryGroupResources, "DesktopsAndApps"),
					}
					if isDDCVersionSupportedForPolicy {
						resources = append(resources,
							BuildPolicySetResource(t, policy_set_testResource),
						)
					}
					if !isPre2407AndOnPremises {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
							BuildServiceAccountResourceAD(t, testServiceAccountResourceAD_updated))
					} else {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_without_serv_acc_uid_delete_machine, "", "ActiveDirectory"),
						)
					}
					resources = append(resources,
						BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
						BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
						BuildZoneResource(t, zoneInput, true),
					)
					return composeTestResourceTf(resources...)
				}(),
				Check: func() resource.TestCheckFunc {
					checks := []resource.TestCheckFunc{
						/*** Verify Application ***/
						// Verify name of application
						resource.TestCheckResourceAttr("citrix_application.testApplication", "name", applicationName),
						// Verify description of application
						resource.TestCheckResourceAttr("citrix_application.testApplication", "description", "Application for testing"),
						// Verify the number of delivery groups
						resource.TestCheckResourceAttr("citrix_application.testApplication", "delivery_groups.#", "1"),
						// Verify the command line executable
						resource.TestCheckResourceAttr("citrix_application.testApplication", "installed_app_properties.command_line_executable", "test.exe"),
					}

					if isDDCVersionSupportedForPolicy {
						// /*** Verify Policy Set ***/
						checks = append(checks,
							// Verify name of the policy set
							resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "name", os.Getenv("TEST_POLICY_SET_NAME")+"-1"),
							// Verify description of the policy set
							resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "description", "Test policy set description"),

							// Verify type of the policy set
							resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "type", "DeliveryGroupPolicies"),
							// Verify the number of scopes of the policy set
							resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "scopes.#", "0"),
							// Verify the number of policies in the policy set
							resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.#", "2"),
							// Verify name of the first policy in the policy set
							resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.0.name", "first-test-policy"),
							// Verify policy settings of the first policy in the policy set
							resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.0.policy_settings.#", "3"),
							resource.TestCheckTypeSetElemNestedAttrs("citrix_policy_set.testPolicySet", "policies.0.policy_settings.*", map[string]string{
								"name":        "AdvanceWarningPeriod",
								"use_default": "false",
								"value":       "13:00:00",
							}),
							resource.TestCheckTypeSetElemNestedAttrs("citrix_policy_set.testPolicySet", "policies.0.policy_settings.*", map[string]string{
								"name":        "AllowFileDownload",
								"enabled":     "true",
								"use_default": "false",
							}),
							// Verify name of the second policy in the policy set
							resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.1.name", "second-test-policy"),
							resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.1.policy_settings.#", "1"),
							resource.TestCheckTypeSetElemNestedAttrs("citrix_policy_set.testPolicySet", "policies.1.policy_settings.*", map[string]string{
								"name":        "AdvanceWarningPeriod",
								"use_default": "true",
							}),
						)
					}

					checks = append(checks,
						/*** Verify Admin Scope ***/
						// Verify the name of the admin scope
						resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "name", adminScopeName),
						// Verify the description of the admin scope
						resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "description", "test scope created via terraform"),

						/*** Verify Admin Role ***/
						// Verify the name of the admin role
						resource.TestCheckResourceAttr("citrix_admin_role.test_role", "name", adminRoleName),
						// Verify the description of the admin role
						resource.TestCheckResourceAttr("citrix_admin_role.test_role", "description", "Test role created via terraform"),
						// Verify the value of the can_launch_manage flag (Set to true by default)
						resource.TestCheckResourceAttr("citrix_admin_role.test_role", "can_launch_manage", "true"),
						// Verify the value of the can_launch_monitor flag (Set to true by default)
						resource.TestCheckResourceAttr("citrix_admin_role.test_role", "can_launch_monitor", "true"),
						// Verify the permissions list
						resource.TestCheckResourceAttr("citrix_admin_role.test_role", "permissions.#", "2"),
						resource.TestCheckTypeSetElemAttr("citrix_admin_role.test_role", "permissions.*", "Director_DismissAlerts"),
						resource.TestCheckTypeSetElemAttr("citrix_admin_role.test_role", "permissions.*", "DesktopGroup_AddApplicationGroup"),
					)
					return resource.ComposeAggregateTestCheckFunc(checks...)
				}(),
			},

			// ImportState testing - Application
			{
				ResourceName:      "citrix_application.testApplication",
				ImportState:       true,
				ImportStateVerify: true,
				// The last_updated attribute does not exist in the Orchestration
				// API, therefore there is no value for it during import.
				ImportStateVerifyIgnore: []string{"delivery_groups", "installed_app_properties"},
			},
			// ImportState testing
			{
				ResourceName:      "citrix_policy_set.testPolicySet",
				ImportState:       true,
				ImportStateVerify: true,
				// The last_updated attribute does not exist in the Orchestration
				// API, therefore there is no value for it during import.
				ImportStateVerifyIgnore: []string{"last_updated", "assigned"},
				SkipFunc:                skipForPolicySet(isDDCVersionSupportedForPolicy),
			},
			// ImportState testing - Admin Scope
			{
				ResourceName:      "citrix_admin_scope.test_scope",
				ImportState:       true,
				ImportStateVerify: true,
				// The last_updated attribute does not exist in the Orchestration
				// API, therefore there is no value for it during import.
				ImportStateVerifyIgnore: []string{"last_updated"},
			},
			// ImportState testing - Admin Role
			{
				ResourceName:      "citrix_admin_role.test_role",
				ImportState:       true,
				ImportStateVerify: true,
				// The last_updated attribute does not exist in the Orchestration
				// API, therefore there is no value for it during import.
				ImportStateVerifyIgnore: []string{"last_updated", "permissions"},
			},

			// Update and Read testing
			{
				Config: func() string {
					resources := []string{
						BuildAdminRoleResource(t, adminRoleTestResource_updated),
						BuildAdminScopeResource(t, adminScopeTestResource_updated),
					}
					if isDDCVersionSupportedForPolicy {
						resources = append(resources, BuildPolicySetResource(t, policy_set_updated_testResource))
					}
					resources = append(resources,
						BuildApplicationResource(t, testApplicationResource_updated),
						BuildAdminFolderResourceWithTwoTypes(t, testAdminFolderResource_twoTypes, "ContainsMachineCatalogs", "ContainsApplications"),
						BuildDeliveryGroupResource(t, testDeliveryGroupResources, "DesktopsAndApps"),
					)
					if !isPre2407AndOnPremises {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
							BuildServiceAccountResourceAD(t, testServiceAccountResourceAD_updated))
					} else {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_without_serv_acc_uid_delete_machine, "", "ActiveDirectory"),
						)
					}
					resources = append(resources,
						BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
						BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
						BuildZoneResource(t, zoneInput, true),
					)
					return composeTestResourceTf(resources...)
				}(),
				Check: func() resource.TestCheckFunc {
					checks := []resource.TestCheckFunc{
						/*** Verify Application ***/
						// Verify name of application
						resource.TestCheckResourceAttr("citrix_application.testApplication", "name", fmt.Sprintf("%s-updated", applicationName)),
						// Verify description of application
						resource.TestCheckResourceAttr("citrix_application.testApplication", "description", "Application for testing updated"),
						// Verify the command line arguments
						resource.TestCheckResourceAttr("citrix_application.testApplication", "installed_app_properties.command_line_arguments", "update test arguments"),
						// Verify the command line executable
						resource.TestCheckResourceAttr("citrix_application.testApplication", "installed_app_properties.command_line_executable", "updated_test.exe"),
						// Verify the application folder path
						resource.TestCheckResourceAttr("citrix_application.testApplication", "application_folder_path", folder_name_2),
					}

					// Only test PolicySet when isDDCVersionSupportedForPolicy is true
					if isDDCVersionSupportedForPolicy {
						policySetChecks := []resource.TestCheckFunc{
							// Verify name of the policy set
							resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "name", os.Getenv("TEST_POLICY_SET_NAME")+"-3"),
							// Verify description of the policy set
							resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "description", "Test policy set description updated"),
							// Verify type of the policy set
							resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "type", "DeliveryGroupPolicies"),
							// Verify the number of scopes of the policy set
							resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "scopes.#", "0"),
							// Verify the number of policies in the policy set
							resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.#", "1"),
							// Verify name of the second policy in the policy set
							resource.TestCheckResourceAttr("citrix_policy_set.testPolicySet", "policies.0.name", "first-test-policy"),
						}
						checks = append(checks, policySetChecks...)
					}

					// Add remaining checks
					remainingChecks := []resource.TestCheckFunc{
						/*** Verify Admin Scope ***/
						// Verify the name of the admin scope
						resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "name", fmt.Sprintf("%s-updated", adminScopeName)),
						// Verify the description of the admin scope
						resource.TestCheckResourceAttr("citrix_admin_scope.test_scope", "description", "Updated description for test scope"),

						/*** Verify Admin Role ***/
						// Verify the name of the admin role
						resource.TestCheckResourceAttr("citrix_admin_role.test_role", "name", fmt.Sprintf("%s-updated", adminRoleName)),
						// Verify the description of the admin role
						resource.TestCheckResourceAttr("citrix_admin_role.test_role", "description", "Updated description for test role"),
						// Verify the value of the can_launch_manage flag
						resource.TestCheckResourceAttr("citrix_admin_role.test_role", "can_launch_manage", "true"),
						// Verify the value of the can_launch_monitor flag
						resource.TestCheckResourceAttr("citrix_admin_role.test_role", "can_launch_monitor", "true"),
						// Verify the permissions list
						resource.TestCheckResourceAttr("citrix_admin_role.test_role", "permissions.#", "3"),
						resource.TestCheckTypeSetElemAttr("citrix_admin_role.test_role", "permissions.*", "Director_DismissAlerts"),
						resource.TestCheckTypeSetElemAttr("citrix_admin_role.test_role", "permissions.*", "ApplicationGroup_AddScope"),
						resource.TestCheckTypeSetElemAttr("citrix_admin_role.test_role", "permissions.*", "AppLib_AddPackage"),
					}
					checks = append(checks, remainingChecks...)

					return resource.ComposeAggregateTestCheckFunc(checks...)
				}(),
			},

			/****************** Admin User Test - On-Premises test only ******************/
			// Create and Read testing
			{
				Config: func() string {
					resources := []string{
						BuildAdminUserResource(t, adminUserTestResource),
						BuildAdminRoleResource(t, adminRoleTestResource_updated),
						BuildAdminScopeResource(t, adminScopeTestResource_updated),
						BuildDeliveryGroupResource(t, testDeliveryGroupResources, "DesktopsAndApps"),
					}
					if !isPre2407AndOnPremises {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
							BuildServiceAccountResourceAD(t, testServiceAccountResourceAD_updated))
					} else {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_without_serv_acc_uid_delete_machine, "", "ActiveDirectory"),
						)
					}
					resources = append(resources,
						BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
						BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
						BuildZoneResource(t, zoneInput, true),
					)
					return composeTestResourceTf(resources...)
				}(),
				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify the name of the admin user
					resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "name", userName),
					// Verify the domain of the admin use
					resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "domain_name", userDomainName),
					// Verify the rights object
					resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.#", "1"),
					resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.0.role", fmt.Sprintf("%s-updated", adminRoleName)),
					resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.0.scope", fmt.Sprintf("%s-updated", adminScopeName)),
					// Verify the is_enabled flag
					resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "is_enabled", "true"),
				),
				SkipFunc: skipForCloud(isOnPremises),
			},
			// ImportState testing
			{
				ResourceName:      "citrix_admin_user.test_admin_user",
				ImportState:       true,
				ImportStateVerify: true,
				// The last_updated attribute does not exist in the Orchestration
				// API, therefore there is no value for it during import.
				ImportStateVerifyIgnore: []string{"last_updated"},
				SkipFunc:                skipForCloud(isOnPremises),
			},
			// Update and Read testing
			{
				Config: func() string {
					resources := []string{
						BuildAdminUserResource(t, adminUserTestResource_updated),
						BuildAdminRoleResource(t, adminRoleTestResource_updated),
						BuildAdminScopeResource(t, adminScopeTestResource_updated),
						BuildDeliveryGroupResource(t, testDeliveryGroupResources, "DesktopsAndApps"),
					}
					if !isPre2407AndOnPremises {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_delete_machine, "", "ActiveDirectory"),
							BuildServiceAccountResourceAD(t, testServiceAccountResourceAD_updated))
					} else {
						resources = append(resources,
							BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_without_serv_acc_uid_delete_machine, "", "ActiveDirectory"),
						)
					}
					resources = append(resources,
						BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
						BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
						BuildZoneResource(t, zoneInput, true),
					)
					return composeTestResourceTf(resources...)
				}(),
				Check: resource.ComposeAggregateTestCheckFunc(
					// Verify the name of the admin user
					resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "name", userName),
					// Verify the domain of the admin user
					resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "domain_name", userDomainName),
					// Verify the updated rights object
					resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.#", "2"),
					resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.0.role", fmt.Sprintf("%s-updated", adminRoleName)),
					resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.0.scope", fmt.Sprintf("%s-updated", adminScopeName)),
					resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.1.role", "Delivery Group Administrator"),
					resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "rights.1.scope", fmt.Sprintf("%s-updated", adminScopeName)),
					// Verify the is_enabled flag
					resource.TestCheckResourceAttr("citrix_admin_user.test_admin_user", "is_enabled", "true"),
				),
				SkipFunc: skipForCloud(isOnPremises),
			},
		},
	})
}

func composeAzureMachineCatalogTestResourceTf(t *testing.T, isOnPremises bool, isPre2407AndOnPremises bool) string {
	zoneInput := os.Getenv("TEST_ZONE_INPUT_AZURE")

	if isOnPremises {
		resources := []string{

			BuildMachineCatalogResourceManualPowerManagedAzure(t, machinecatalog_testResources_manual_power_managed_azure),
		}
		if !isPre2407AndOnPremises {
			resources = append(resources,
				BuildMachineCatalogWithZeroMachines(t, machinecatalog_testResources_zeroMachines_azure),
				BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure, "-HybAAD", "HybridAzureAD"),
				BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure, "", "ActiveDirectory"),
				BuildServiceAccountResourceAD(t, testServiceAccountResourceAD_updated),
			)
		} else {
			resources = append(resources,
				BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_without_serv_acc_uid, "-HybAAD", "HybridAzureAD"),
				BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure_without_serv_acc_uid, "", "ActiveDirectory"),
			)
		}
		resources = append(resources,
			BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
			BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
			BuildZoneResource(t, zoneInput, true),
		)
		return composeTestResourceTf(resources...)
	}
	return composeTestResourceTf(
		BuildMachineCatalogWithZeroMachines(t, machinecatalog_testResources_zeroMachines_azure),
		BuildMachineCatalogResourceManualPowerManagedAzure(t, machinecatalog_testResources_manual_power_managed_azure),
		BuildMachineCatalogResourceWorkgroup(t, machinecatalog_testResources_workgroup),
		BuildMachineCatalogResourceAzureAd(t, machinecatalog_testResources_azure_ad),
		BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure, "-HybAAD", "HybridAzureAD"),
		BuildMachineCatalogResourceAzure(t, machinecatalog_testResources_azure, "", "ActiveDirectory"),
		BuildServiceAccountResourceAD(t, testServiceAccountResourceAD_updated),
		BuildHypervisorResourcePoolResourceAzure(t, hypervisor_resource_pool_updated_testResource_azure),
		BuildHypervisorResourceAzure(t, hypervisor_testResources_updated),
		BuildZoneResource(t, zoneInput, true),
	)
}

func composeCloudMachineCatalogTestVerification(isOnPremises bool, aadCatalogName, workgroupCatalogName string) resource.TestCheckFunc {
	if isOnPremises {
		// For OnPremises, do not return any cloud related test verification
		return resource.ComposeAggregateTestCheckFunc()
	}
	return resource.ComposeAggregateTestCheckFunc(
		/*** Verify MCS AAD Machine Catalog ***/
		// Verify name of catalog
		resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "name", aadCatalogName),
		// Verify domain FQDN
		resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "session_support", "MultiSession"),
		// Verify machine catalog identity type
		resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "provisioning_scheme.identity_type", "AzureAD"),
		// Verify nic network
		resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-AAD", "provisioning_scheme.network_mapping.0.network", os.Getenv("TEST_MC_SUBNET")),

		/*** Verify MCS Workgroup Machine Catalog ***/
		// Verify name of catalog
		resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-WG", "name", workgroupCatalogName),
		// Verify domain FQDN
		resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-WG", "session_support", "MultiSession"),
		// Verify machine catalog identity type
		resource.TestCheckResourceAttr("citrix_machine_catalog.testMachineCatalog-WG", "provisioning_scheme.identity_type", "Workgroup"),
	)
}
