package export

import (
	"context"
	"errors"
	"testing"

	"go.uber.org/mock/gomock"

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

func TestServerProxiesExportRPCs(t *testing.T) {
	t.Run("list exports", func(t *testing.T) {
		ctrl := gomock.NewController(t)
		client := mock_nextgenglobal.NewMockNextGenGlobal(ctrl)
		server := NewServer(client)
		ctx := context.Background()
		request := &globalngv1.ListExportsRequest{}
		response := &globalngv1.ListExportsResponse{}
		clientErr := errors.New("list exports failed")
		sameRequest := gomock.Cond(func(got *globalngv1.ListExportsRequest) bool { return got == request })

		client.EXPECT().ListExports(ctx, sameRequest).Return(response, nil)
		got, err := server.ListExports(ctx, request)
		if err != nil {
			t.Fatalf("ListExports() unexpected error: %v", err)
		}
		if got != response {
			t.Fatal("ListExports() did not return the client response unchanged")
		}

		client.EXPECT().ListExports(ctx, sameRequest).Return(nil, clientErr)
		got, err = server.ListExports(ctx, request)
		if got != nil || !errors.Is(err, clientErr) {
			t.Fatalf("ListExports() = (%v, %v), want (nil, %v)", got, err, clientErr)
		}
	})

	t.Run("get export", func(t *testing.T) {
		ctrl := gomock.NewController(t)
		client := mock_nextgenglobal.NewMockNextGenGlobal(ctrl)
		server := NewServer(client)
		ctx := context.Background()
		request := &globalngv1.GetExportRequest{}
		response := &globalngv1.Export{}
		clientErr := errors.New("get export failed")
		sameRequest := gomock.Cond(func(got *globalngv1.GetExportRequest) bool { return got == request })

		client.EXPECT().GetExport(ctx, sameRequest).Return(response, nil)
		got, err := server.GetExport(ctx, request)
		if err != nil {
			t.Fatalf("GetExport() unexpected error: %v", err)
		}
		if got != response {
			t.Fatal("GetExport() did not return the client response unchanged")
		}

		client.EXPECT().GetExport(ctx, sameRequest).Return(nil, clientErr)
		got, err = server.GetExport(ctx, request)
		if got != nil || !errors.Is(err, clientErr) {
			t.Fatalf("GetExport() = (%v, %v), want (nil, %v)", got, err, clientErr)
		}
	})

	t.Run("create export", func(t *testing.T) {
		ctrl := gomock.NewController(t)
		client := mock_nextgenglobal.NewMockNextGenGlobal(ctrl)
		server := NewServer(client)
		ctx := context.Background()
		request := &globalngv1.CreateExportRequest{}
		response := &globalngv1.Export{}
		clientErr := errors.New("create export failed")
		sameRequest := gomock.Cond(func(got *globalngv1.CreateExportRequest) bool { return got == request })

		client.EXPECT().CreateExport(ctx, sameRequest).Return(response, nil)
		got, err := server.CreateExport(ctx, request)
		if err != nil {
			t.Fatalf("CreateExport() unexpected error: %v", err)
		}
		if got != response {
			t.Fatal("CreateExport() did not return the client response unchanged")
		}

		client.EXPECT().CreateExport(ctx, sameRequest).Return(nil, clientErr)
		got, err = server.CreateExport(ctx, request)
		if got != nil || !errors.Is(err, clientErr) {
			t.Fatalf("CreateExport() = (%v, %v), want (nil, %v)", got, err, clientErr)
		}
	})

	t.Run("delete export", func(t *testing.T) {
		ctrl := gomock.NewController(t)
		client := mock_nextgenglobal.NewMockNextGenGlobal(ctrl)
		server := NewServer(client)
		ctx := context.Background()
		request := &globalngv1.DeleteExportRequest{}
		response := &globalngv1.Export{}
		clientErr := errors.New("delete export failed")
		sameRequest := gomock.Cond(func(got *globalngv1.DeleteExportRequest) bool { return got == request })

		client.EXPECT().DeleteExport(ctx, sameRequest).Return(response, nil)
		got, err := server.DeleteExport(ctx, request)
		if err != nil {
			t.Fatalf("DeleteExport() unexpected error: %v", err)
		}
		if got != response {
			t.Fatal("DeleteExport() did not return the client response unchanged")
		}

		client.EXPECT().DeleteExport(ctx, sameRequest).Return(nil, clientErr)
		got, err = server.DeleteExport(ctx, request)
		if got != nil || !errors.Is(err, clientErr) {
			t.Fatalf("DeleteExport() = (%v, %v), want (nil, %v)", got, err, clientErr)
		}
	})

	t.Run("cancel export", func(t *testing.T) {
		ctrl := gomock.NewController(t)
		client := mock_nextgenglobal.NewMockNextGenGlobal(ctrl)
		server := NewServer(client)
		ctx := context.Background()
		request := &globalngv1.CancelExportRequest{}
		response := &globalngv1.Export{}
		clientErr := errors.New("cancel export failed")
		sameRequest := gomock.Cond(func(got *globalngv1.CancelExportRequest) bool { return got == request })

		client.EXPECT().CancelExport(ctx, sameRequest).Return(response, nil)
		got, err := server.CancelExport(ctx, request)
		if err != nil {
			t.Fatalf("CancelExport() unexpected error: %v", err)
		}
		if got != response {
			t.Fatal("CancelExport() did not return the client response unchanged")
		}

		client.EXPECT().CancelExport(ctx, sameRequest).Return(nil, clientErr)
		got, err = server.CancelExport(ctx, request)
		if got != nil || !errors.Is(err, clientErr) {
			t.Fatalf("CancelExport() = (%v, %v), want (nil, %v)", got, err, clientErr)
		}
	})
}
