package data

import (
	"fmt"
	"strconv"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/shared-provider/pkg/types"
	"github.com/tidbcloud/shared-provider/pkg/utils/labels"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

const (
	defaultTiDBReplicas = 1
	defaultPDReplicas   = 1
	defaultTiKVReplicas = 1

	defaultAWSInstanceType = "aws_sharedtier_6"
	defaultGCPInstanceType = "gcp_sharedtier_6"
)

type ClusterPatch func(c *cloudv1.Cluster) *cloudv1.Cluster

func (p ClusterPatch) Patch(obj client.Object) client.Object {
	c, ok := obj.(*cloudv1.Cluster)
	if !ok {
		return obj
	}
	return p(c)
}

func NewDefaultCluster(ns string, net *cloudv1.Network) *cloudv1.Cluster {
	enablePublic := false
	instanceType := defaultAWSInstanceType
	if net.Spec.Provider == types.ProviderTypeGCPSharedTier {
		instanceType = defaultGCPInstanceType
	}
	return &cloudv1.Cluster{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "default-cluster",
			Namespace: ns,
			Labels: map[string]string{ // add more labels if needed
				labels.LabelKeyProject: labels.GetProjectFromLabels(net.Labels),
			},
		},
		Spec: cloudv1.ClusterSpec{
			NetworkName: net.Name,
			SqlEndpoints: cloudv1.SqlEndpoints{
				Public: cloudv1.Service{
					Enabled: &enablePublic,
				},
			},
			Cluster: cloudv1.ClusterTopology{
				TiDB: cloudv1.TiDB{
					Replicas:     defaultTiDBReplicas,
					InstanceType: instanceType,
				},
				TiKV: cloudv1.TiKV{
					Replicas:     defaultTiKVReplicas,
					InstanceType: instanceType,
				},
				PD: cloudv1.PD{
					Replicas:     defaultPDReplicas,
					InstanceType: instanceType,
				},
			},
		},
	}
}

func ClusterWithPrivateLink(principal, endpoint string) ClusterPatch {
	return func(c *cloudv1.Cluster) *cloudv1.Cluster {
		if c.Annotations == nil {
			c.Annotations = map[string]string{}
		}
		if principal != "" {
			principal = strconv.Quote(principal)
		}
		if endpoint != "" {
			endpoint = strconv.Quote(endpoint)
		}
		c.Annotations["alpha.privatelink.tidbcloud.com/spec"] =
			fmt.Sprintf(`{"allowedPrincipals":[%s],"acceptanceRequired":true,"allowedVPCEndpoints":[%s]}`, principal, endpoint)

		return c
	}
}
