package models

import (
	"context"
	"os"
	"testing"

	"github.com/stretchr/testify/assert"
)

var sharedBucketBundle *SharedBucketBundle

func TestMain(m *testing.M) {
	sharedBucketBundle = initSharedBucketData()

	code := m.Run()
	os.Exit(code)
}

func TestSharedBucketFilter(t *testing.T) {
	accounts := []SharedBucketInfo{
		{
			BucketName:          "aws-bucket1",
			AWSSharedBucketInfo: &AWSSharedBucketInfo{},
		},
		{
			BucketName:          "aws-bucket2",
			AWSSharedBucketInfo: &AWSSharedBucketInfo{},
		},
		{
			BucketName:          "aws-bucket3",
			AWSSharedBucketInfo: &AWSSharedBucketInfo{},
		},
		{
			BucketName:          "aws-bucket4",
			AWSSharedBucketInfo: &AWSSharedBucketInfo{},
		},
		{
			BucketName:          "gcp-bucket1",
			GCPSharedBucketInfo: &GCPSharedBucketInfo{},
		},
		{
			BucketName:          "gcp-bucket2",
			GCPSharedBucketInfo: &GCPSharedBucketInfo{},
		},
		{
			BucketName:            "azure-bucket1",
			AzureSharedBucketInfo: &AzureSharedBucketInfo{},
		},
		{
			BucketName:            "azure-bucket2",
			AzureSharedBucketInfo: &AzureSharedBucketInfo{},
		},
	}
	filter := SharedBucketFilter{}
	filteredAccounts := filter.Apply(accounts)
	assert.Equal(t, 8, len(filteredAccounts))
}

func TestSharedBucketInfo(t *testing.T) {
	t.Run("GetKey", func(t *testing.T) {
		assert.Equal(t, "aws-bucket1", SharedBucketInfo{
			BucketName:          "aws-bucket1",
			AWSSharedBucketInfo: &AWSSharedBucketInfo{},
		}.GetKey())
		assert.Equal(t, "gcp-bucket1", SharedBucketInfo{
			BucketName:          "gcp-bucket1",
			GCPSharedBucketInfo: &GCPSharedBucketInfo{},
		}.GetKey())
		assert.Equal(t, "", SharedBucketInfo{}.GetKey())
		assert.Equal(t, "azure-bucket1", SharedBucketInfo{
			BucketName:            "azure-bucket1",
			AzureSharedBucketInfo: &AzureSharedBucketInfo{},
		}.GetKey())
	})
	t.Run("Is", func(t *testing.T) {
		assert.True(t, SharedBucketInfo{
			BucketName:          "aws-bucket1",
			AWSSharedBucketInfo: &AWSSharedBucketInfo{},
		}.Is("aws-bucket1"))
		assert.False(t, SharedBucketInfo{
			BucketName:          "aws-bucket1",
			AWSSharedBucketInfo: &AWSSharedBucketInfo{},
		}.Is("aws-bucket2"))
		assert.True(t, SharedBucketInfo{
			BucketName:          "gcp-bucket1",
			GCPSharedBucketInfo: &GCPSharedBucketInfo{},
		}.Is("gcp-bucket1"))
		assert.False(t, SharedBucketInfo{
			BucketName:          "gcp-bucket1",
			GCPSharedBucketInfo: &GCPSharedBucketInfo{},
		}.Is("gcp-bucket2"))
		assert.False(t, DataPlaneAccountInfo{}.Is("project2"))
		assert.True(t, SharedBucketInfo{
			BucketName:            "azure-bucket1",
			AzureSharedBucketInfo: &AzureSharedBucketInfo{},
		}.Is("azure-bucket1"))
		assert.False(t, SharedBucketInfo{
			BucketName:            "azure-bucket1",
			AzureSharedBucketInfo: &AzureSharedBucketInfo{},
		}.Is("azure-bucket2"))
	})
}

func Test_SharedBucketBundle(t *testing.T) {
	t.Run("list", func(t *testing.T) {
		list, err := sharedBucketBundle.List(context.TODO())
		assert.NoError(t, err)
		assert.NotEmpty(t, list)
		assert.Equal(t, 2, len(list))
	})
	t.Run("list with filter", func(t *testing.T) {
		list, err := sharedBucketBundle.List(context.TODO(), SharedBucketFilter{})
		assert.NoError(t, err)
		assert.Equal(t, []SharedBucketInfo{
			{BucketName: "aws-bucket1", AWSSharedBucketInfo: &AWSSharedBucketInfo{}},
			{BucketName: "aws-bucket2", AWSSharedBucketInfo: &AWSSharedBucketInfo{}},
		}, list)
	})
	t.Run("get default", func(t *testing.T) {
		a, err := sharedBucketBundle.GetDefault(context.TODO())
		assert.NoError(t, err)
		assert.NotEmpty(t, a)
		assert.Equal(t, "aws-bucket2", a.BucketName)
	})
	t.Run("create", func(t *testing.T) {
		err := sharedBucketBundle.Create(context.TODO(), &SharedBucketInfo{
			BucketName:          "new-bucket",
			AWSSharedBucketInfo: &AWSSharedBucketInfo{},
		})
		assert.NoError(t, err)
	})
	t.Run("set to default", func(t *testing.T) {
		err := sharedBucketBundle.SetToDefault(context.TODO(), "aws-bucket1")
		assert.NoError(t, err)
		a, err := sharedBucketBundle.GetDefault(context.TODO())
		assert.NoError(t, err)
		assert.NotEmpty(t, a)
		assert.Equal(t, "aws-bucket1", a.BucketName)
	})
}

func initSharedBucketData() *SharedBucketBundle {
	sharedBucketList := []SharedBucketInfo{
		{
			BucketName:          "aws-bucket1",
			AWSSharedBucketInfo: &AWSSharedBucketInfo{},
		},
		{
			BucketName:          "aws-bucket2",
			AWSSharedBucketInfo: &AWSSharedBucketInfo{},
		},
	}
	return &SharedBucketBundle{
		DefaultBucketName: "aws-bucket2",
		Buckets:           sharedBucketList,
	}
}
