package clusterproxy_test

import (
	"context"
	"testing"

	"github.com/golang/mock/gomock"
	"github.com/stretchr/testify/assert"
	cspb "github.com/tidbcloud/cluster-service-ng/api/cluster-service-ng/v1beta"
	dedicatedv1 "github.com/tidbcloud/cluster-service-ng/api/tidbcloud/dataplane-manager/v1"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/runtime/schema"

	"github.com/tidbcloud/ticdc-service-ng/pkg/clusterproxy"
	"github.com/tidbcloud/ticdc-service-ng/pkg/clusterproxy/client"
	"github.com/tidbcloud/ticdc-service-ng/pkg/config"
	"github.com/tidbcloud/ticdc-service-ng/pkg/regionalservice/mocks"
)

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

	mockRegionalCli := mocks.NewMockClient(ctrl)
	cfg := &config.Config{}
	model := clusterproxy.NewClusterProxyModelImpl(cfg, mockRegionalCli, client.DefaultClientCreator)

	ctx := context.Background()
	clusterIdStr := "12345"
	proxyBaseUrl := "http://proxy.url"
	tidbGroup := &cspb.TiDBGroup{
		Id:            "456",
		SharedPoolId:  "1234",
		DataplaneName: "dpname",
	}

	// Mock the GetDataPlaneAndTimeGroupByClusterID method
	mockRegionalCli.EXPECT().GetDataPlaneByID(ctx, tidbGroup.DataplaneName).Return(&dedicatedv1.DataPlane{
		ApiGateway: proxyBaseUrl,
		AuthToken:  "test-token",
	}, nil).Times(1)
	mockRegionalCli.EXPECT().GetOneTiDBGroupByClusterID(ctx, clusterIdStr).Return(tidbGroup, nil).AnyTimes()

	// Test the GetClusterProxy method
	proxy, err := model.GetClusterProxy(ctx, clusterIdStr, clusterproxy.DefaultClusterProxyTimeout)
	assert.NoError(t, err)
	assert.NotNil(t, proxy)
}

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

	mockRegionalCli := mocks.NewMockClient(ctrl)
	cfg := &config.Config{}
	model := clusterproxy.NewClusterProxyModelImpl(cfg, mockRegionalCli, nil)

	ctx := context.Background()
	clusterIdStr := "12345"

	mockRegionalCli.EXPECT().GetOneTiDBGroupByClusterID(ctx, clusterIdStr).
		Return(nil, apierrors.NewNotFound(schema.GroupResource{}, clusterIdStr)).AnyTimes()

	// Test the GetClusterProxy method
	_, err := model.GetClusterProxy(ctx, clusterIdStr, clusterproxy.DefaultClusterProxyTimeout)
	assert.Error(t, err)
	assert.Equal(t, codes.NotFound, status.Code(err))
}

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

	mockRegionalCli := mocks.NewMockClient(ctrl)
	cfg := &config.Config{}
	model := clusterproxy.NewClusterProxyModelImpl(cfg, mockRegionalCli, nil)

	ctx := context.Background()
	clusterIdStr := "12345"

	// Mock the GetDataPlaneAndTimeGroupByClusterID method to return internal error
	mockRegionalCli.EXPECT().GetOneTiDBGroupByClusterID(ctx, clusterIdStr).
		Return(nil, status.Errorf(codes.Internal, "internal error")).Times(1)

	// Test the GetClusterProxy method
	_, err := model.GetClusterProxy(ctx, clusterIdStr, clusterproxy.DefaultClusterProxyTimeout)
	assert.Error(t, err)
	assert.Equal(t, codes.Internal, status.Code(err))
}
