package cluster

import (
	"context"
	"strings"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/utils/pointer"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

const (
	externalConfigName      = "external-prometheus-config"
	externalConfigNamespace = "infra"
	dashboardKey            = "dashboard-config"
	prometheusConfigKey     = "prometheus-config"
	// For the ossinsight cluster:
	// - Prometheus consumes 1.5Gi memory for 5600 sample/s writes.
	// - There are 2 tidb 3 flash 3 kv in the cluster.
	// We need to limit prom memory usage to 1 Gi.
	// @XUYIFAN02 CURRENTLY NOT USED
	promSampleLimit = "5000"
)

// externalLabels are labels that add to time series or alerts in Prometheus.
type ExternalLabels struct {
	// ClusterName is like `shoot/aws/us-west-2/shoot--nightly--10cfb004`.
	ClusterName string
	Project     string
	// ShootName is like `10cfb004`.
	ShootName    string
	SeedRegion   string
	SeedProvider string
	ShootInfra   string
	TenantID     string
	// ClusterID is like `tidb123456`.
	ClusterID string
}

func ExternalPrometheusConfig(infraCli client.Client, namespace string, labels *ExternalLabels) (*corev1.ConfigMap, error) {
	promConfig := new(corev1.ConfigMap)
	err := infraCli.Get(context.TODO(), types.NamespacedName{
		Namespace: externalConfigNamespace,
		Name:      externalConfigName,
	}, promConfig)
	if err != nil {
		return nil, err
	}

	return &corev1.ConfigMap{
		TypeMeta: metav1.TypeMeta{
			APIVersion: "v1",
			Kind:       "ConfigMap",
		},
		ObjectMeta: metav1.ObjectMeta{
			Namespace: namespace,
			Name:      externalConfigName,
		},
		Immutable: pointer.Bool(false),
		Data: map[string]string{
			"dashboard-config":  promConfig.Data[dashboardKey],
			"prometheus-config": populatePrometheusConfig(promConfig.Data[prometheusConfigKey], namespace, labels),
		},
	}, nil
}

func populatePrometheusConfig(config string, namespace string, labels *ExternalLabels) (res string) {
	res = strings.ReplaceAll(config, "TIDB_NAMESPACE", namespace)
	res = strings.ReplaceAll(res, "CLUSTER_NAME", labels.ClusterName)
	res = strings.ReplaceAll(res, "CLUSTER_ID", labels.ClusterID)
	res = strings.ReplaceAll(res, "TENANT_ID", labels.TenantID)
	res = strings.ReplaceAll(res, "PROJECT", labels.Project)
	res = strings.ReplaceAll(res, "SHOOT_NAME", labels.ShootName)
	res = strings.ReplaceAll(res, "SHOOT_INFRA", labels.ShootInfra)
	res = strings.ReplaceAll(res, "SEED_REGION", labels.SeedRegion)
	res = strings.ReplaceAll(res, "SEED_PROVIDER", labels.SeedProvider)
	// @XUYIFAN02 CURRENTLY NOT USED
	res = strings.ReplaceAll(res, "PROM_SAMPLE_LIMIT", promSampleLimit)
	return
}
