package adapterimpl

import (
	"fmt"
	"math"
	"net/url"
	"testing"

	"github.com/onsi/gomega"

	globalserverlessv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/serverless/v1"
	regionalserverlessv1 "github.com/tidbcloud/tidb-management-service/api/spec/regional/serverless/v1"
	"github.com/tidbcloud/tidb-management-service/serverless-global-service/infra/adapterimpl/cvt"
)

func TestConvertFieldValueToString(t *testing.T) {
	g := gomega.NewWithT(t)

	req := &globalserverlessv1.ServerlessServiceListRequest{
		Filter: &globalserverlessv1.ClusterFilter{
			ProjectIds: []uint64{1369847559691457760, math.MaxInt64},
			ClusterIds: []string{"12sadfdasdfadsgfasge34t543sadf", "234asdfadfasftwtredsacbaadfgbsdb sb"},
			TenantIds:  []uint64{13698475596914577601, math.MaxInt64},
			States: []regionalserverlessv1.ClusterState{
				regionalserverlessv1.ClusterState_CLUSTER_STATE_READY,
				regionalserverlessv1.ClusterState_CLUSTER_STATE_DELETED,
				regionalserverlessv1.ClusterState_CLUSTER_STATE_CREATING,
			},
		},
	}
	queryParams, err := protobufStructToMap(cvt.ListReq2RegionSvcListReq(req))
	g.Expect(err).To(gomega.Succeed())

	values := []url.Values{}
	for key, value := range queryParams {
		switch val := value.(type) {
		case []any:
			values = append(values, convertArrayFieldValueToValues(key, val))
		default:
		}
	}

	for _, val := range values {
		for key, params := range val {
			switch key {
			case "project_ids":
				g.Expect(sliceUint64Equals(req.Filter.ProjectIds, params)).To(gomega.BeTrue())
			case "tenant_ids":
				g.Expect(sliceUint64Equals(req.Filter.TenantIds, params)).To(gomega.BeTrue())
			case "cluster_ids":
				g.Expect(slicStringeEquals(req.Filter.ClusterIds, params)).To(gomega.BeTrue())
			case "states":
				g.Expect(slicStateEquals(req.Filter.States, params)).To(gomega.BeTrue())
			}
		}
	}
}

func sliceUint64Equals(actual []uint64, expect []string) bool {
	if len(actual) != len(expect) {
		return false
	}

	for i, v := range actual {
		if fmt.Sprintf("%v", v) != expect[i] {
			return false
		}
	}

	return true
}

func slicStringeEquals(actual, expect []string) bool {
	if len(actual) != len(expect) {
		return false
	}

	for i, v := range actual {
		if v != expect[i] {
			return false
		}
	}

	return true
}

func slicStateEquals(actual []regionalserverlessv1.ClusterState, expect []string) bool {
	if len(actual) != len(expect) {
		return false
	}

	for i, v := range actual {
		if v.String() != expect[i] {
			return false
		}
	}

	return true
}
