package slprober

import (
	"context"
	"fmt"
	"regexp"

	opv2 "github.com/pingcap/tidb-operator/api/v2/core/v1alpha1"
	tidbClusterV1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1"

	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
)

const (
	ClusterPrefix = "db"
	LabelCluster  = "tags.tidbcloud.com/cluster"
	LabelGroup    = "pingcap.com/group"
)

func getClusterID(cluster *tidbClusterV1alpha1.TidbCluster) string {
	// for gardener arch
	clusterID := getClusterLabel(cluster, TiDBClusterClusterIDLabel)
	if clusterID == "" {
		clusterID = getClusterLabel(cluster, TiDBClusterClusterIDLabelAlt)
	}
	// for new arch
	if clusterID == "" {
		clusterID = getClusterIDFromNamespace(cluster.Namespace)
	}
	return clusterID
}

func getClusterIDFromTiDBGroup(tg *opv2.TiDBGroup) string {
	clusterID := tg.Labels[LabelCluster]
	if clusterID == "" {
		clusterID = getClusterIDFromNamespace(tg.Namespace)
	}
	return clusterID
}

func getClusterIDFromTiProxyGroup(tg *opv2.TiProxyGroup) string {
	clusterID := tg.Labels[LabelCluster]
	if clusterID == "" {
		clusterID = getClusterIDFromNamespace(tg.Namespace)
	}
	return clusterID
}

// infra-provider will create TiDBCluster CR in `tidb<ClusterID>` namespace in dataplane.
func getClusterIDFromNamespace(namespace string) string {
	if len(namespace) < 4 {
		return ""
	}
	return namespace[4:]
}

func getClusterLabel(c *tidbClusterV1alpha1.TidbCluster, key string) string {
	if c == nil {
		return ""
	}
	if c.Labels == nil {
		return ""
	}
	v, ok := c.Labels[key]
	if !ok {
		return ""
	}
	return v
}

func IsClusterInCreatingStatus(
	ctx context.Context,
	kubeCli kubernetes.Interface,
	tc *tidbClusterV1alpha1.TidbCluster,
) (bool, error) {
	if tc.Labels[TiDBClusterStatusFromCentral] == string(TidbClusterCreating) {
		return true, nil
	}
	initializerJob, err := kubeCli.BatchV1().
		Jobs(tc.GetNamespace()).
		Get(ctx,
			TiDBInitializerMemberName(ClusterPrefix), metav1.GetOptions{})
	if err != nil {
		if errors.IsNotFound(err) {
			return false, nil
		}
		return true, fmt.Errorf("failed to get initializer job: %s", err.Error())
	}
	if initializerJob.Status.Succeeded == 0 {
		return true, nil
	}
	return false, nil
}

func TiDBInitializerMemberName(clusterName string) string {
	return fmt.Sprintf("%s-tidb-initializer", clusterName)
}

// tc name: rg\d+-op\d+-c\d+.*|changefeed-\d+|ticdc-\d+
func IsTiCDCTC(tc *tidbClusterV1alpha1.TidbCluster) (bool, error) {
	if tc == nil {
		return false, nil
	}
	regexpStr := `^(rg\d+-op\d+-c\d+.*|changefeed-\d+|ticdc-\d+)$`
	matched, err := regexp.MatchString(regexpStr, tc.Name)
	if err != nil {
		return false, fmt.Errorf("failed to match tc name with regexp: %s", err.Error())
	}
	return matched, nil
}
