package br

import (
	"context"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"go.uber.org/mock/gomock"

	globalngv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/domain/entity"
	encryptionkeyrepo "github.com/tidbcloud/tidb-management-service/nextgen-global-service/domain/repository/encryptionkey"
	mockencryptionkeyrepo "github.com/tidbcloud/tidb-management-service/nextgen-global-service/domain/repository/encryptionkey/mock_encryptionkey"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
)

func TestResolverResolveByClusters(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	mockEncryptionKeyRepo := mockencryptionkeyrepo.NewMockRepo(ctrl)

	resolver := NewResolver(mockEncryptionKeyRepo)
	clusters := map[uint64]*entity.Cluster{
		1: {
			Cluster:         &globalngv1.Cluster{ClusterId: 1},
			EncryptionKeyId: 0,
		},
		2: {
			Cluster:         &globalngv1.Cluster{ClusterId: 2},
			EncryptionKeyId: 10,
		},
		3: {
			Cluster:         &globalngv1.Cluster{ClusterId: 3},
			EncryptionKeyId: 20,
		},
	}

	mockEncryptionKeyRepo.EXPECT().
		ListEncryptionKeys(gomock.Any(), gomock.Any()).
		DoAndReturn(func(_ context.Context, filter *encryptionkeyrepo.Filter) ([]*entity.EncryptionKey, bizerr.BizError) {
			assert.ElementsMatch(t, []uint64{10, 20}, filter.Ids)
			return []*entity.EncryptionKey{
				{
					Id:              10,
					CustomerManaged: false,
				},
			}, nil
		})

	snapshots, err := resolver.ResolveByClusters(t.Context(), clusters)
	require.NoError(t, err)

	assert.Equal(t, Snapshot{}, snapshots[1])
	assert.Equal(t, Snapshot{
		CustomerManaged: false,
		EncryptionKeyId: 10,
	}, snapshots[2])
	assert.Equal(t, Snapshot{
		CustomerManaged: false,
		EncryptionKeyId: 20,
	}, snapshots[3])
}

func TestResolverResolveByCluster(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	mockEncryptionKeyRepo := mockencryptionkeyrepo.NewMockRepo(ctrl)

	resolver := NewResolver(mockEncryptionKeyRepo)
	cluster := &entity.Cluster{
		Cluster:         &globalngv1.Cluster{ClusterId: 10},
		EncryptionKeyId: 123,
	}

	mockEncryptionKeyRepo.EXPECT().
		ListEncryptionKeys(gomock.Any(), gomock.Any()).
		DoAndReturn(func(_ context.Context, filter *encryptionkeyrepo.Filter) ([]*entity.EncryptionKey, bizerr.BizError) {
			assert.Equal(t, []uint64{123}, filter.Ids)
			return []*entity.EncryptionKey{
				{
					Id:              123,
					CustomerManaged: true,
				},
			}, nil
		})

	snapshot, err := resolver.ResolveByCluster(t.Context(), cluster)
	require.NoError(t, err)
	assert.Equal(t, Snapshot{
		CustomerManaged: true,
		EncryptionKeyId: 123,
	}, snapshot)
}
