package backup

import (
	"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"
	openapingv1beta2 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/nextgen/v1beta2"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/adapter/account/mock_account"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/adapter/nextgenglobal/mock_nextgenglobal"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/entity"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/nextgen/cluster/mock_cluster"
	"github.com/tidbcloud/tidb-management-service/utilities/grpc/metadata"
)

func TestValidateDeleteBackupRequestDeniesWhenIdentityHasNoBackupMutationRole(t *testing.T) {
	ctx := t.Context()
	orgID := uint64(60205)
	projectID := uint64(3201779)
	clusterID := uint64(1001)
	userID := "70637"

	ctl := gomock.NewController(t)
	defer ctl.Finish()

	mockNextGenCli := mock_nextgenglobal.NewMockNextGenGlobal(ctl)
	mockClusterSvc := mock_cluster.NewMockService(ctl)
	mockAccountCli := mock_account.NewMockClient(ctl)

	server := &serverImpl{
		nextGenCli: mockNextGenCli,
		clusterSvc: mockClusterSvc,
		accountCli: mockAccountCli,
	}
	reqMeta := &metadata.RequestMeta{OrgID: orgID, UserID: userID}

	mockNextGenCli.EXPECT().
		ListBackups(gomock.Any(), &globalngv1.ListBackupsRequest{
			OrganizationIds: []string{"60205"},
			BackupIds:       []string{"backup-1"},
		}).
		Return(&globalngv1.ListBackupsResponse{
			Backups:   []*globalngv1.Backup{{Id: "backup-1", ClusterId: "1001"}},
			TotalSize: 1,
		}, nil)
	mockClusterSvc.EXPECT().
		GetCluster(gomock.Any(), clusterID, entity.ClusterViewClusterViewLocal, true).
		Return(&entity.Cluster{
			ClusterId:      clusterID,
			ProjectId:      projectID,
			OrganizationId: orgID,
		}, nil)
	mockAccountCli.EXPECT().
		CheckBackupMutationPermission(gomock.Any(), orgID, projectID, clusterID, userID).
		Return(false, nil)

	backup, err := server.validateDeleteBackupRequest(ctx, &openapingv1beta2.DeleteBackupRequest{BackupId: "backup-1"}, reqMeta)

	require.Error(t, err)
	assert.Nil(t, backup)
	assert.Contains(t, err.Error(), "permission")
}

func TestValidateDeleteBackupRequestAllowsWhenIdentityHasBackupMutationRole(t *testing.T) {
	ctx := t.Context()
	orgID := uint64(60205)
	projectID := uint64(3201779)
	clusterID := uint64(1001)
	userID := "70637"

	ctl := gomock.NewController(t)
	defer ctl.Finish()

	mockNextGenCli := mock_nextgenglobal.NewMockNextGenGlobal(ctl)
	mockClusterSvc := mock_cluster.NewMockService(ctl)
	mockAccountCli := mock_account.NewMockClient(ctl)

	server := &serverImpl{
		nextGenCli: mockNextGenCli,
		clusterSvc: mockClusterSvc,
		accountCli: mockAccountCli,
	}
	reqMeta := &metadata.RequestMeta{OrgID: orgID, UserID: userID}

	mockNextGenCli.EXPECT().
		ListBackups(gomock.Any(), &globalngv1.ListBackupsRequest{
			OrganizationIds: []string{"60205"},
			BackupIds:       []string{"backup-1"},
		}).
		Return(&globalngv1.ListBackupsResponse{
			Backups:   []*globalngv1.Backup{{Id: "backup-1", ClusterId: "1001"}},
			TotalSize: 1,
		}, nil)
	mockClusterSvc.EXPECT().
		GetCluster(gomock.Any(), clusterID, entity.ClusterViewClusterViewLocal, true).
		Return(&entity.Cluster{
			ClusterId:      clusterID,
			ProjectId:      projectID,
			OrganizationId: orgID,
		}, nil)
	mockAccountCli.EXPECT().
		CheckBackupMutationPermission(gomock.Any(), orgID, projectID, clusterID, userID).
		Return(true, nil)

	backup, err := server.validateDeleteBackupRequest(ctx, &openapingv1beta2.DeleteBackupRequest{BackupId: "backup-1"}, reqMeta)

	require.NoError(t, err)
	require.NotNil(t, backup)
	assert.Equal(t, "backup-1", backup.GetId())
}
