package metric_agent

import (
	"context"
	"fmt"
	"strings"

	ec2v1alpha1 "github.com/crossplane-contrib/provider-aws/apis/ec2/v1alpha1"
	"sigs.k8s.io/controller-runtime/pkg/client"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/infra-provider/pkg/namer"
)

const (
	TidbCloudBizTypeValue         = "tidbcloud"
	TidbCloudBizTypeValue4Dev     = "dev-tidbcloud"
	TidbCloudBizTypeValue4Staging = "staging-tidbcloud"
)

// MatchRegion checks if the current region supports o11y infra.
// The patterns are set in pulumi yaml files, named "o11y-infra.effective-region".
func MatchRegion(region string, patterns []string) bool {
	for _, pattern := range patterns {
		if strings.Contains(pattern, region) {
			return true
		}
	}
	return false
}

// FindReusableVPCEndpointName tries to find a reusable vpc endpoint, so we do not need to create a new one.
// The reusable vpc endpoint should have the same service name and vpc id as given.
func FindReusableVPCEndpointName(ctx context.Context, infraCli client.Client, serviceName, vpcID, epType string) (string, error) {
	epListInNewArch := &ec2v1alpha1.VPCEndpointList{}
	err := infraCli.List(ctx, epListInNewArch)
	if err != nil {
		return "", fmt.Errorf("failed to list vpc endpoint: %w", err)
	}
	for i, endpoint := range epListInNewArch.Items {
		if isVPCEndpointReusable(&endpoint, serviceName, vpcID, epType) {
			return epListInNewArch.Items[i].Name, nil
		}
	}

	return "", nil
}

func isVPCEndpointReusable(endpoint *ec2v1alpha1.VPCEndpoint, serviceName, vpcID, epType string) bool {
	return endpoint.Spec.ForProvider.ServiceName != nil &&
		*endpoint.Spec.ForProvider.ServiceName == serviceName &&
		endpoint.Spec.ForProvider.VPCID != nil &&
		*endpoint.Spec.ForProvider.VPCID == vpcID &&
		endpoint.Spec.ForProvider.VPCEndpointType != nil &&
		*endpoint.Spec.ForProvider.VPCEndpointType == epType
}

// GKEPSCEndpointName is just like metric_agent.InterfaceEndpointName.
// but this function ensures:
// - the name does not exceed 63 characters
// - the name in different cluster but in the same network may be the same (so it can be shared)
func GKEPSCEndpointName(domainName string, network *cloudv1.Network) string {
	// The final endpoint name is concatenated by o11y domain name and a vpc/gke identifier.
	// Currently, the o11y domain name's length is 26 (maybe change),
	// to avoid the final name exceeds 63 characters,
	// generate a shorterIdentifier with length 20.
	shorterIdentifier := namer.UniqueIdentifier(network.ObjectMeta, namer.WithLimit(namer.GKEK8sIdentLimit))
	return InterfaceEndpointName(domainName, shorterIdentifier)
}

func GetTidbCloudBizTypeByEnv(env string) string {
	switch env {
	case "dev":
		return TidbCloudBizTypeValue4Dev
	case "staging":
		return TidbCloudBizTypeValue4Staging
	default:
		return TidbCloudBizTypeValue
	}
}
