package backup

import (
	"context"
	"testing"

	"github.com/stretchr/testify/require"
	"go.uber.org/mock/gomock"
	"google.golang.org/grpc"

	globalngv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"
	globalserverlessv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/serverless/v1"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/adapter/nextgenglobal/mock_nextgenglobal"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/adapter/serverlessglobal"
)

type fakeServerlessGlobal struct {
	serverlessglobal.ServerlessGlobal
}

func TestOverrideFlexibleBackupRetention(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()
	nextgenCli := mock_nextgenglobal.NewMockNextGenGlobal(ctrl)
	server := NewServer(nextgenCli, &fakeServerlessGlobal{})
	req := &globalngv1.OverrideFlexibleBackupRetentionRequest{
		ClusterId:     "1",
		RetentionDays: 1,
		Reason:        "test",
	}
	want := &globalngv1.BackupSetting{ClusterId: "1", RetentionDays: &req.RetentionDays}
	nextgenCli.EXPECT().OverrideFlexibleBackupRetention(gomock.Any(), req).Return(want, nil)

	resp, err := server.OverrideFlexibleBackupRetention(t.Context(), req)

	require.NoError(t, err)
	require.Same(t, want, resp)
}

func TestListBackupsProxy(t *testing.T) {
	req := &globalserverlessv1.ListPGBackupsRequest{ClusterId: "c1", MaxCount: 1}
	want := &globalserverlessv1.ListPGBackupsResponse{HasMore: false}

	server := serverImpl{
		serverlessCli: &fakeServerlessGlobalList{resp: want},
	}

	resp, err := server.ListPGBackups(t.Context(), req)
	require.NoError(t, err)
	require.Same(t, want, resp)
}

func TestCreatePGBackupProxy(t *testing.T) {
	req := &globalserverlessv1.CreatePGBackupRequest{ClusterId: "c1"}
	want := &globalserverlessv1.CreatePGBackupResponse{BackupId: 1}

	server := serverImpl{
		serverlessCli: &fakeServerlessGlobalList{createResp: want},
	}

	resp, err := server.CreatePGBackup(t.Context(), req)
	require.NoError(t, err)
	require.Same(t, want, resp)
}

func TestGetPGBackupProxy(t *testing.T) {
	req := &globalserverlessv1.GetPGBackupRequest{ClusterId: "c1", BackupId: 1}
	want := &globalserverlessv1.GetPGBackupResponse{}

	server := serverImpl{
		serverlessCli: &fakeServerlessGlobalList{getBackupResp: want},
	}

	resp, err := server.GetPGBackup(t.Context(), req)
	require.NoError(t, err)
	require.Same(t, want, resp)
}

func TestGetPGBackupPolicyProxy(t *testing.T) {
	req := &globalserverlessv1.GetPGBackupPolicyRequest{ClusterId: "c1"}
	want := &globalserverlessv1.GetPGBackupPolicyResponse{}

	server := serverImpl{
		serverlessCli: &fakeServerlessGlobalList{getPolicyResp: want},
	}

	resp, err := server.GetPGBackupPolicy(t.Context(), req)
	require.NoError(t, err)
	require.Same(t, want, resp)
}

func TestUpdatePGBackupPolicyProxy(t *testing.T) {
	req := &globalserverlessv1.UpdatePGBackupPolicyRequest{ClusterId: "c1"}
	want := &globalserverlessv1.UpdatePGBackupPolicyResponse{}

	server := serverImpl{
		serverlessCli: &fakeServerlessGlobalList{updatePolicyResp: want},
	}

	resp, err := server.UpdatePGBackupPolicy(t.Context(), req)
	require.NoError(t, err)
	require.Same(t, want, resp)
}

type fakeServerlessGlobalList struct {
	serverlessglobal.ServerlessGlobal

	resp             *globalserverlessv1.ListPGBackupsResponse
	createResp       *globalserverlessv1.CreatePGBackupResponse
	getBackupResp    *globalserverlessv1.GetPGBackupResponse
	getPolicyResp    *globalserverlessv1.GetPGBackupPolicyResponse
	updatePolicyResp *globalserverlessv1.UpdatePGBackupPolicyResponse
}

func (f *fakeServerlessGlobalList) CreatePGBackup(
	_ context.Context,
	_ *globalserverlessv1.CreatePGBackupRequest,
	_ ...grpc.CallOption,
) (*globalserverlessv1.CreatePGBackupResponse, error) {
	return f.createResp, nil
}

func (f *fakeServerlessGlobalList) ListPGBackups(
	_ context.Context,
	_ *globalserverlessv1.ListPGBackupsRequest,
	_ ...grpc.CallOption,
) (*globalserverlessv1.ListPGBackupsResponse, error) {
	return f.resp, nil
}

func (f *fakeServerlessGlobalList) GetPGBackup(
	_ context.Context,
	_ *globalserverlessv1.GetPGBackupRequest,
	_ ...grpc.CallOption,
) (*globalserverlessv1.GetPGBackupResponse, error) {
	return f.getBackupResp, nil
}

func (f *fakeServerlessGlobalList) GetPGBackupPolicy(
	_ context.Context,
	_ *globalserverlessv1.GetPGBackupPolicyRequest,
	_ ...grpc.CallOption,
) (*globalserverlessv1.GetPGBackupPolicyResponse, error) {
	return f.getPolicyResp, nil
}

func (f *fakeServerlessGlobalList) UpdatePGBackupPolicy(
	_ context.Context,
	_ *globalserverlessv1.UpdatePGBackupPolicyRequest,
	_ ...grpc.CallOption,
) (*globalserverlessv1.UpdatePGBackupPolicyResponse, error) {
	return f.updatePolicyResp, nil
}
