package grpc_service

import (
	"context"
	"fmt"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/tidbcloud/config-center/internal/db"
	"github.com/tidbcloud/config-center/internal/service"
	pb "github.com/tidbcloud/config-center/proto/config_center"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"k8s.io/utils/ptr"
)

func TestUpdateGetClusterComponent(t *testing.T) {
	assert := assert.New(t)
	mockDB := db.NewMockDB()
	c := &ConfigCenterService{
		DB: mockDB,
		UnifiedService: &service.ConfigCenterService{
			DB: mockDB,
		},
	}

	_, err := c.UpdateComponentImage(context.TODO(), &pb.UpdateComponentImageRequest{
		ClusterType:      pb.ClusterType_DEDICATED_TIDB,
		ComponentName:    "tidb",
		ComponentVersion: "v4.0.0",
		BaseImage:        "docker.io/pingcap/tidb",
		Tag:              "v4.0.0-123",
	})
	assert.Nil(err)

	_, err = c.UpdateClusterComponent(context.TODO(), &pb.UpdateClusterComponentRequest{
		ClusterType:   pb.ClusterType_DEDICATED_TIDB,
		ClusterId:     "tidb123123",
		ComponentName: "tidb",
		CloudProvider: ptr.To("aws"),
		Version:       ptr.To("v4.0.0"),
		// AllowMissing:  false,
	})
	assert.NotNil(err)

	// should failed if not exist and version is not set
	_, err = c.UpdateClusterComponent(context.TODO(), &pb.UpdateClusterComponentRequest{
		ClusterType:   pb.ClusterType_DEDICATED_TIDB,
		ClusterId:     "tidb123123",
		ComponentName: "tidb",
		CloudProvider: ptr.To("aws"),
		// Version:       ptr.To("v4.0.0"),
		AllowMissing: true,
	})
	assert.NotNil(err)

	// should not exist when validate_only is true
	compV, err := c.UpdateClusterComponent(context.TODO(), &pb.UpdateClusterComponentRequest{
		ClusterType:   pb.ClusterType_DEDICATED_TIDB,
		ClusterId:     "tidb123123",
		ComponentName: "tidb",
		CloudProvider: ptr.To("aws"),
		Version:       ptr.To("v4.0.0"),
		AllowMissing:  true,
		ValidateOnly:  true,
	})
	assert.Nil(err)
	assert.NotNil(compV)
	assert.Equal("v4.0.0-123", compV.EffectiveImageTag)
	assert.Equal("docker.io/pingcap/tidb", compV.BaseImage)
	assert.Equal("", compV.OverwriteImageTag)
	_, err = c.GetClusterComponent(context.TODO(), &pb.GetClusterComponentRequest{
		ClusterType:   pb.ClusterType_DEDICATED_TIDB,
		ClusterId:     "tidb123123",
		ComponentName: "tidb",
	})
	assert.NotNil(err)
	assert.Equal(codes.NotFound, status.Code(err))

	component, err := c.UpdateClusterComponent(context.TODO(), &pb.UpdateClusterComponentRequest{
		ClusterType:   pb.ClusterType_DEDICATED_TIDB,
		ClusterId:     "tidb123123",
		ComponentName: "tidb",
		CloudProvider: ptr.To("aws"),
		Version:       ptr.To("v4.0.0"),
		AllowMissing:  true,
	})
	assert.Nil(err)
	assert.NotNil(component)
	assert.Equal("v4.0.0-123", component.EffectiveImageTag)
	assert.Equal("docker.io/pingcap/tidb", component.BaseImage)
	assert.Equal("", component.OverwriteImageTag)

	component2, err := c.UpdateClusterComponent(context.TODO(), &pb.UpdateClusterComponentRequest{
		ClusterType:   pb.ClusterType_DEDICATED_TIDB,
		ClusterId:     "tidb123123",
		ComponentName: "tidb",
		CloudProvider: ptr.To("aws"),
		// Version:           ptr.To("v4.0.0"),
		OverwriteImageTag: ptr.To("v4.0.0-2333"),
	})

	fmt.Println(err)
	assert.Nil(err)
	assert.NotNil(component2)
	assert.Equal("v4.0.0-2333", component2.EffectiveImageTag)
	assert.Equal("docker.io/pingcap/tidb", component.BaseImage)
	assert.Equal("v4.0.0", component2.Version)
	assert.Equal("v4.0.0-2333", component2.OverwriteImageTag)
}

func TestSearchClusterComponentsRegionalRequiresLogicalRegion(t *testing.T) {
	assert := assert.New(t)
	mockDB := db.NewMockDB()
	c := &ConfigCenterService{
		DB:          mockDB,
		ServiceMode: ModeGlobal,
		UnifiedService: &service.ConfigCenterService{
			DB: mockDB,
		},
	}

	resp, err := c.SearchClusterComponents(context.TODO(), &pb.SearchClusterComponentsRequest{
		ClusterType:   pb.ClusterType_SHARED_POOL,
		ComponentName: "tidb",
	})
	assert.Nil(resp)
	assert.NotNil(err)
	assert.Equal(codes.InvalidArgument, status.Code(err))
	assert.Contains(err.Error(), "logical_region is required")
}
