package br

import (
	"context"
	"errors"
	"testing"

	v1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
	v1alpha1br "github.com/pingcap/tidb-operator/api/v2/br/v1alpha1"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	apiv1 "github.com/tidbcloud/cluster-service-ng/api/cluster-service-ng/v1beta"
	"github.com/tidbcloud/cluster-service-ng/domain/entity"
	"github.com/tidbcloud/cluster-service-ng/domain/workflow"
	"github.com/tidbcloud/cluster-service-ng/pkg/cert"
	dataplanemocks "github.com/tidbcloud/cluster-service-ng/pkg/dataplane/mocks"
	externalmocks "github.com/tidbcloud/cluster-service-ng/pkg/externalmocks/mocks"
	"github.com/tidbcloud/cluster-service-ng/pkg/runtime/actions"
	"github.com/tidbcloud/cluster-service-ng/pkg/storage/mysql/schema"
	repomocks "github.com/tidbcloud/cluster-service-ng/pkg/storage/repo/mocks"
	"github.com/tidbcloud/cluster-service-ng/pkg/tioperator"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

func TestDeleteTiBRGCAction_Start(t *testing.T) {
	tests := []struct {
		name             string
		args             actions.ActionArgs
		gcRepo           *repomocks.BackupGcSettingRepo
		sharedPoolRepo   *repomocks.SharedPoolRepo
		dataplaneManager *dataplanemocks.Manager
		mockClient       *externalmocks.Client
		expectError      bool
		errorContains    string
	}{
		{
			name: "missing shared pool ID",
			args: actions.ActionArgs{},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				return mock
			}(),
			mockClient:    nil,
			expectError:   true,
			errorContains: "failed to get shared pool id",
		},
		{
			name: "backup gc setting not found - should skip",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(nil, status.Error(codes.NotFound, "not found"))
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				return mock
			}(),
			mockClient:    nil,
			expectError:   false,
			errorContains: "",
		},
		{
			name: "backup gc setting load fails with non-NotFound error",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(nil, errors.New("database error"))
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				return mock
			}(),
			mockClient:    nil,
			expectError:   true,
			errorContains: "failed to load backup gc setting",
		},
		{
			name: "backup gc setting status not SP_RUNNING or SP_CREATING - should skip",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				backupGcSetting := &entity.BackupGcSetting{
					BackupGcSetting: schema.BackupGcSetting{
						Status: schema.BackupGcStatusSPDeleted, // Not SP_RUNNING or SP_CREATING
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(backupGcSetting, nil)
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				return mock
			}(),
			mockClient:    nil,
			expectError:   false,
			errorContains: "",
		},
		{
			name: "shared pool load fails",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				backupGcSetting := &entity.BackupGcSetting{
					BackupGcSetting: schema.BackupGcSetting{
						Status: schema.BackupGcStatusSPRunning,
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(backupGcSetting, nil)
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				mock.EXPECT().Load(context.TODO(), "test-sharedpool", true).Return(nil, errors.New("shared pool not found"))
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				return mock
			}(),
			mockClient:    nil,
			expectError:   true,
			errorContains: "failed to load sharedPool",
		},
		{
			name: "dataplane manager get client fails",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				backupGcSetting := &entity.BackupGcSetting{
					BackupGcSetting: schema.BackupGcSetting{
						Status: schema.BackupGcStatusSPRunning,
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(backupGcSetting, nil)
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				sharedPool := &entity.SharedPool{
					SharedPool: apiv1.SharedPool{
						Id:            "test-sharedpool",
						DataplaneName: "test-dataplane",
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool", true).Return(sharedPool, nil)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				mock.EXPECT().GetClient("test-dataplane").Return(nil, errors.New("dataplane client error"))
				return mock
			}(),
			mockClient:    nil,
			expectError:   true,
			errorContains: "failed to get remote client for shared pool",
		},
		{
			name: "successful deletion - SPRunning",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				backupGcSetting := &entity.BackupGcSetting{
					BackupGcSetting: schema.BackupGcSetting{
						Status: schema.BackupGcStatusSPRunning,
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(backupGcSetting, nil)
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				sharedPool := &entity.SharedPool{
					SharedPool: apiv1.SharedPool{
						Id:            "test-sharedpool",
						DataplaneName: "test-dataplane",
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool", true).Return(sharedPool, nil)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				mockClient := externalmocks.NewClient(t)
				// Mock successful deletion of certificate and TiBRGC
				// Use the actual certificate object that cert.TiBRGCRCert() returns
				expectedCert := cert.TiBRGCRCert(tioperator.DefaultTiBRGCRName, "tidbtest-sharedpool")
				mockClient.EXPECT().Delete(context.TODO(), expectedCert).Return(nil)
				mockClient.EXPECT().Delete(context.TODO(), &v1alpha1br.TiBRGC{
					ObjectMeta: metav1.ObjectMeta{
						Name:      tioperator.DefaultTiBRGCRName,
						Namespace: "tidbtest-sharedpool",
					},
				}).Return(nil)
				mock.EXPECT().GetClient("test-dataplane").Return(mockClient, nil)
				return mock
			}(),
			mockClient:    externalmocks.NewClient(t),
			expectError:   false,
			errorContains: "",
		},
		{
			name: "successful deletion - SPCreating",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				backupGcSetting := &entity.BackupGcSetting{
					BackupGcSetting: schema.BackupGcSetting{
						Status: schema.BackupGcStatusSPCreating,
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(backupGcSetting, nil)
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				sharedPool := &entity.SharedPool{
					SharedPool: apiv1.SharedPool{
						Id:            "test-sharedpool",
						DataplaneName: "test-dataplane",
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool", true).Return(sharedPool, nil)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				mockClient := externalmocks.NewClient(t)
				// Mock successful deletion of certificate and TiBRGC
				// Use the actual certificate object that cert.TiBRGCRCert() returns
				expectedCert := cert.TiBRGCRCert(tioperator.DefaultTiBRGCRName, "tidbtest-sharedpool")
				mockClient.EXPECT().Delete(context.TODO(), expectedCert).Return(nil)
				mockClient.EXPECT().Delete(context.TODO(), &v1alpha1br.TiBRGC{
					ObjectMeta: metav1.ObjectMeta{
						Name:      tioperator.DefaultTiBRGCRName,
						Namespace: "tidbtest-sharedpool",
					},
				}).Return(nil)
				mock.EXPECT().GetClient("test-dataplane").Return(mockClient, nil)
				return mock
			}(),
			mockClient:    externalmocks.NewClient(t),
			expectError:   false,
			errorContains: "",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			action := &deleteTiBRGCAction{
				gcRepo:           tt.gcRepo,
				sharedPoolRepo:   tt.sharedPoolRepo,
				dataplaneManager: tt.dataplaneManager,
			}

			err := action.Start(tt.args)

			if tt.expectError {
				require.Error(t, err)
				assert.Contains(t, err.Error(), tt.errorContains)
			} else {
				require.NoError(t, err)
			}
		})
	}
}

func TestDeleteTiBRGCAction_CheckFinish(t *testing.T) {
	tests := []struct {
		name             string
		args             actions.ActionArgs
		gcRepo           *repomocks.BackupGcSettingRepo
		sharedPoolRepo   *repomocks.SharedPoolRepo
		dataplaneManager *dataplanemocks.Manager
		mockClient       *externalmocks.Client
		expectedResult   bool
		expectError      bool
		errorContains    string
	}{
		{
			name: "missing shared pool ID",
			args: actions.ActionArgs{},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				return mock
			}(),
			mockClient:     nil,
			expectedResult: false,
			expectError:    true,
			errorContains:  "failed to get shared pool id",
		},
		{
			name: "backup gc setting load fails",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(nil, errors.New("database error"))
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				return mock
			}(),
			mockClient:     nil,
			expectedResult: false,
			expectError:    true,
			errorContains:  "failed to load backup gc setting",
		},
		{
			name: "backup gc setting status not SP_RUNNING or SP_CREATING - already deleted",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				backupGcSetting := &entity.BackupGcSetting{
					BackupGcSetting: schema.BackupGcSetting{
						Status: schema.BackupGcStatusSPDeleted, // Not SP_RUNNING or SP_CREATING
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(backupGcSetting, nil)
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				return mock
			}(),
			mockClient:     nil,
			expectedResult: true, // Already deleted, should return true
			expectError:    false,
		},
		{
			name: "shared pool load fails",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				backupGcSetting := &entity.BackupGcSetting{
					BackupGcSetting: schema.BackupGcSetting{
						Status: schema.BackupGcStatusSPRunning,
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(backupGcSetting, nil)
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				mock.EXPECT().Load(context.TODO(), "test-sharedpool", true).Return(nil, errors.New("shared pool not found"))
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				return mock
			}(),
			mockClient:     nil,
			expectedResult: false,
			expectError:    true,
			errorContains:  "failed to load sharedPool",
		},
		{
			name: "dataplane manager get client fails",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				backupGcSetting := &entity.BackupGcSetting{
					BackupGcSetting: schema.BackupGcSetting{
						Status: schema.BackupGcStatusSPRunning,
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(backupGcSetting, nil)
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				sharedPool := &entity.SharedPool{
					SharedPool: apiv1.SharedPool{
						Id:            "test-sharedpool",
						DataplaneName: "test-dataplane",
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool", true).Return(sharedPool, nil)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				mock.EXPECT().GetClient("test-dataplane").Return(nil, errors.New("dataplane client error"))
				return mock
			}(),
			mockClient:     nil,
			expectedResult: false,
			expectError:    true,
			errorContains:  "failed to get remote client for shared pool",
		},
		{
			name: "certificate still exists - not finished",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				backupGcSetting := &entity.BackupGcSetting{
					BackupGcSetting: schema.BackupGcSetting{
						Status: schema.BackupGcStatusSPRunning,
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(backupGcSetting, nil)
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				sharedPool := &entity.SharedPool{
					SharedPool: apiv1.SharedPool{
						Id:            "test-sharedpool",
						DataplaneName: "test-dataplane",
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool", true).Return(sharedPool, nil)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				mockClient := externalmocks.NewClient(t)
				certificate := &v1.Certificate{
					ObjectMeta: metav1.ObjectMeta{
						Name:      tioperator.DefaultTiBRGCRName,
						Namespace: "tidbtest-sharedpool",
					},
				}
				mockClient.EXPECT().Get(context.TODO(), client.ObjectKeyFromObject(certificate), certificate).Return(nil) // Certificate still exists
				mock.EXPECT().GetClient("test-dataplane").Return(mockClient, nil)
				return mock
			}(),
			mockClient:     externalmocks.NewClient(t),
			expectedResult: false, // Not finished because certificate still exists
			expectError:    false,
		},
		{
			name: "certificate get fails with non-NotFound error",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				backupGcSetting := &entity.BackupGcSetting{
					BackupGcSetting: schema.BackupGcSetting{
						Status: schema.BackupGcStatusSPRunning,
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(backupGcSetting, nil)
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				sharedPool := &entity.SharedPool{
					SharedPool: apiv1.SharedPool{
						Id:            "test-sharedpool",
						DataplaneName: "test-dataplane",
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool", true).Return(sharedPool, nil)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				mockClient := externalmocks.NewClient(t)
				certificate := &v1.Certificate{
					ObjectMeta: metav1.ObjectMeta{
						Name:      tioperator.DefaultTiBRGCRName,
						Namespace: "tidbtest-sharedpool",
					},
				}
				mockClient.EXPECT().Get(context.TODO(), client.ObjectKeyFromObject(certificate), certificate).Return(errors.New("network error"))
				mock.EXPECT().GetClient("test-dataplane").Return(mockClient, nil)
				return mock
			}(),
			mockClient:     externalmocks.NewClient(t),
			expectedResult: false,
			expectError:    true,
			errorContains:  "failed to get tibrgc certificate",
		},
		{
			name: "tibrgc still exists - not finished",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				backupGcSetting := &entity.BackupGcSetting{
					BackupGcSetting: schema.BackupGcSetting{
						Status: schema.BackupGcStatusSPCreating,
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(backupGcSetting, nil)
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				sharedPool := &entity.SharedPool{
					SharedPool: apiv1.SharedPool{
						Id:            "test-sharedpool",
						DataplaneName: "test-dataplane",
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool", true).Return(sharedPool, nil)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				mockClient := externalmocks.NewClient(t)
				certificate := &v1.Certificate{
					ObjectMeta: metav1.ObjectMeta{
						Name:      tioperator.DefaultTiBRGCRName,
						Namespace: "tidbtest-sharedpool",
					},
				}
				tibrgcCR := &v1alpha1br.TiBRGC{
					ObjectMeta: metav1.ObjectMeta{
						Name:      tioperator.DefaultTiBRGCRName,
						Namespace: "tidbtest-sharedpool",
					},
				}
				mockClient.EXPECT().Get(context.TODO(), client.ObjectKeyFromObject(certificate), certificate).Return(apierrors.NewNotFound(v1.Resource("certificate"), tioperator.DefaultTiBRGCRName))
				mockClient.EXPECT().Get(context.TODO(), client.ObjectKeyFromObject(tibrgcCR), tibrgcCR).Return(nil) // TiBRGC still exists
				mock.EXPECT().GetClient("test-dataplane").Return(mockClient, nil)
				return mock
			}(),
			mockClient:     externalmocks.NewClient(t),
			expectedResult: false, // Not finished because TiBRGC still exists
			expectError:    false,
		},
		{
			name: "tibrgc get fails with non-NotFound error",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				backupGcSetting := &entity.BackupGcSetting{
					BackupGcSetting: schema.BackupGcSetting{
						Status: schema.BackupGcStatusSPRunning,
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(backupGcSetting, nil)
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				sharedPool := &entity.SharedPool{
					SharedPool: apiv1.SharedPool{
						Id:            "test-sharedpool",
						DataplaneName: "test-dataplane",
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool", true).Return(sharedPool, nil)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				mockClient := externalmocks.NewClient(t)
				certificate := &v1.Certificate{
					ObjectMeta: metav1.ObjectMeta{
						Name:      tioperator.DefaultTiBRGCRName,
						Namespace: "tidbtest-sharedpool",
					},
				}
				tibrgcCR := &v1alpha1br.TiBRGC{
					ObjectMeta: metav1.ObjectMeta{
						Name:      tioperator.DefaultTiBRGCRName,
						Namespace: "tidbtest-sharedpool",
					},
				}
				mockClient.EXPECT().Get(context.TODO(), client.ObjectKeyFromObject(certificate), certificate).Return(apierrors.NewNotFound(v1.Resource("certificate"), tioperator.DefaultTiBRGCRName))
				mockClient.EXPECT().Get(context.TODO(), client.ObjectKeyFromObject(tibrgcCR), tibrgcCR).Return(errors.New("network error"))
				mock.EXPECT().GetClient("test-dataplane").Return(mockClient, nil)
				return mock
			}(),
			mockClient:     externalmocks.NewClient(t),
			expectedResult: false,
			expectError:    true,
			errorContains:  "failed to get tibrgc",
		},
		{
			name: "successful deletion - both certificate and tibrgc not found",
			args: actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("test-sharedpool"),
			},
			gcRepo: func() *repomocks.BackupGcSettingRepo {
				mock := repomocks.NewBackupGcSettingRepo(t)
				backupGcSetting := &entity.BackupGcSetting{
					BackupGcSetting: schema.BackupGcSetting{
						Status: schema.BackupGcStatusSPRunning,
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool").Return(backupGcSetting, nil)
				return mock
			}(),
			sharedPoolRepo: func() *repomocks.SharedPoolRepo {
				mock := repomocks.NewSharedPoolRepo(t)
				sharedPool := &entity.SharedPool{
					SharedPool: apiv1.SharedPool{
						Id:            "test-sharedpool",
						DataplaneName: "test-dataplane",
					},
				}
				mock.EXPECT().Load(context.TODO(), "test-sharedpool", true).Return(sharedPool, nil)
				return mock
			}(),
			dataplaneManager: func() *dataplanemocks.Manager {
				mock := dataplanemocks.NewManager(t)
				mockClient := externalmocks.NewClient(t)
				certificate := &v1.Certificate{
					ObjectMeta: metav1.ObjectMeta{
						Name:      tioperator.DefaultTiBRGCRName,
						Namespace: "tidbtest-sharedpool",
					},
				}
				tibrgcCR := &v1alpha1br.TiBRGC{
					ObjectMeta: metav1.ObjectMeta{
						Name:      tioperator.DefaultTiBRGCRName,
						Namespace: "tidbtest-sharedpool",
					},
				}
				mockClient.EXPECT().Get(context.TODO(), client.ObjectKeyFromObject(certificate), certificate).Return(apierrors.NewNotFound(v1.Resource("certificate"), tioperator.DefaultTiBRGCRName))
				mockClient.EXPECT().Get(context.TODO(), client.ObjectKeyFromObject(tibrgcCR), tibrgcCR).Return(apierrors.NewNotFound(v1alpha1br.Resource("tibrgc"), tioperator.DefaultTiBRGCRName))
				mock.EXPECT().GetClient("test-dataplane").Return(mockClient, nil)
				return mock
			}(),
			mockClient:     externalmocks.NewClient(t),
			expectedResult: true, // Successfully deleted
			expectError:    false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			action := &deleteTiBRGCAction{
				gcRepo:           tt.gcRepo,
				sharedPoolRepo:   tt.sharedPoolRepo,
				dataplaneManager: tt.dataplaneManager,
			}

			result, err := action.CheckFinish(tt.args)

			if tt.expectError {
				require.Error(t, err)
				assert.Contains(t, err.Error(), tt.errorContains)
			} else {
				require.NoError(t, err)
			}

			assert.Equal(t, tt.expectedResult, result)
		})
	}
}
