/*
Copyright (c) Microsoft Corporation.
Licensed under the MIT license.
*/

package controllers_test

import (
	"testing"

	. "github.com/onsi/gomega"

	eventgrid "github.com/Azure/azure-service-operator/v2/api/eventgrid/v1api20200601"
	storage "github.com/Azure/azure-service-operator/v2/api/storage/v1api20210401"
	"github.com/Azure/azure-service-operator/v2/internal/testcommon"
	"github.com/Azure/azure-service-operator/v2/pkg/genruntime"
)

func Test_EventGrid_Domain(t *testing.T) {
	t.Parallel()

	tc := globalTestContext.ForTest(t)

	rg := tc.CreateTestResourceGroupAndWait()

	publicNetworkAccess := eventgrid.DomainProperties_PublicNetworkAccess_Enabled

	// Create a domain
	domain := &eventgrid.Domain{
		ObjectMeta: tc.MakeObjectMeta("domain"),
		Spec: eventgrid.Domain_Spec{
			Location:            tc.AzureRegion,
			Owner:               testcommon.AsOwner(rg),
			PublicNetworkAccess: &publicNetworkAccess,
		},
	}

	// Create a storage account to use as destination
	accessTier := storage.StorageAccountPropertiesCreateParameters_AccessTier_Hot
	kind := storage.StorageAccount_Kind_Spec_StorageV2
	sku := storage.SkuName_Standard_LRS
	acctName := tc.NoSpaceNamer.GenerateName("dest")
	acct := &storage.StorageAccount{
		ObjectMeta: tc.MakeObjectMetaWithName(acctName),
		Spec: storage.StorageAccount_Spec{
			Location: tc.AzureRegion,
			Owner:    testcommon.AsOwner(rg),
			Kind:     &kind,
			Sku:      &storage.Sku{Name: &sku},
			// TODO: They mark this property as optional but actually it is required
			AccessTier: &accessTier,
		},
	}

	tc.CreateResourcesAndWait(domain, acct)

	queueServices := &storage.StorageAccountsQueueService{
		ObjectMeta: tc.MakeObjectMeta("dest-queues"),
		Spec: storage.StorageAccountsQueueService_Spec{
			Owner: testcommon.AsOwner(acct),
		},
	}

	tc.CreateResourceAndWait(queueServices)

	queue := &storage.StorageAccountsQueueServicesQueue{
		ObjectMeta: tc.MakeObjectMeta("dest-queue"),
		Spec: storage.StorageAccountsQueueServicesQueue_Spec{
			Owner: testcommon.AsOwner(queueServices),
		},
	}

	tc.CreateResourceAndWait(queue)
	armId := *domain.Status.Id
	acctReference := tc.MakeReferenceFromResource(acct)

	tc.RunParallelSubtests(
		testcommon.Subtest{
			Name: "CreateDomainTopicAndSubscription",
			Test: func(tc *testcommon.KubePerTestContext) {
				DomainTopicAndSubscription_CRUD(tc, queue, domain, acctReference)
			},
		},
		testcommon.Subtest{
			Name: "CreateDomainSubscription",
			Test: func(tc *testcommon.KubePerTestContext) {
				DomainSubscription_CRUD(tc, queue, domain, acctReference)
			},
		},
	)

	tc.DeleteResourceAndWait(domain)

	// Ensure that the resource group was really deleted in Azure
	exists, _, err := tc.AzureClient.CheckExistenceWithGetByID(
		tc.Ctx,
		armId,
		string(eventgrid.APIVersion_Value))
	tc.Expect(err).ToNot(HaveOccurred())
	tc.Expect(exists).To(BeFalse())
}

func DomainTopicAndSubscription_CRUD(tc *testcommon.KubePerTestContext, queue *storage.StorageAccountsQueueServicesQueue, domain *eventgrid.Domain, acctReference *genruntime.ResourceReference) {
	topic := &eventgrid.DomainsTopic{
		ObjectMeta: tc.MakeObjectMeta("topic"),
		Spec: eventgrid.DomainsTopic_Spec{
			Owner: testcommon.AsOwner(domain),
		},
	}

	tc.CreateResourceAndWait(topic)
	// don’t bother deleting; deleting domain will clean up

	endpointType := eventgrid.StorageQueueEventSubscriptionDestination_EndpointType_StorageQueue
	subscription := &eventgrid.EventSubscription{
		ObjectMeta: tc.MakeObjectMeta("sub"),
		Spec: eventgrid.EventSubscription_Spec{
			Owner: tc.AsExtensionOwner(topic),
			Destination: &eventgrid.EventSubscriptionDestination{
				StorageQueue: &eventgrid.StorageQueueEventSubscriptionDestination{
					EndpointType: &endpointType,
					// TODO[donotmerge]: These properties used to be in a "Properties" property but are flattened
					// TODO[donotmerge]: in the Swagger branch
					//Properties: &eventgrid.StorageQueueEventSubscriptionDestinationProperties{
					//	ResourceReference: acctReference,
					//	QueueName:         &queue.Name,
					//},
					ResourceReference: acctReference,
					QueueName:         &queue.Name,
				},
			},
		},
	}

	tc.CreateResourceAndWait(subscription)
	// don’t bother deleting
}

func DomainSubscription_CRUD(tc *testcommon.KubePerTestContext, queue *storage.StorageAccountsQueueServicesQueue, domain *eventgrid.Domain, acctReference *genruntime.ResourceReference) {
	endpointType := eventgrid.StorageQueueEventSubscriptionDestination_EndpointType_StorageQueue
	subscription := &eventgrid.EventSubscription{
		ObjectMeta: tc.MakeObjectMeta("sub"),
		Spec: eventgrid.EventSubscription_Spec{
			Owner: tc.AsExtensionOwner(domain),
			Destination: &eventgrid.EventSubscriptionDestination{
				StorageQueue: &eventgrid.StorageQueueEventSubscriptionDestination{
					EndpointType: &endpointType,
					// TODO[donotmerge]: These properties used to be in a "Properties" property but are flattened
					// TODO[donotmerge]: in the Swagger branch
					//Properties: &eventgrid.StorageQueueEventSubscriptionDestinationProperties{
					//	ResourceReference: acctReference,
					//	QueueName:         &queue.Name,
					//},
					ResourceReference: acctReference,
					QueueName:         &queue.Name,
				},
			},
		},
	}

	tc.CreateResourceAndWait(subscription)
	// don’t bother deleting
}
