package metacache

import (
	"context"
	"fmt"
	"sync"

	"sigs.k8s.io/controller-runtime/pkg/client"

	o11yv1 "github.com/tidbcloud/observability/api/regionalserver/resourceworker/v1"
)

const (
	annotationApplicationID = "observability.pingcap.com/applicationID"
)

type MetaInfo struct {
	VMAccountID int32
	VMProjectID int32
}

type MetaCache interface {
	GetMetaInfo(ctx context.Context, env, tenant, cluster string, nextGen bool, byoc bool) (*MetaInfo, error)
}

func NewMetaCache(kubecli client.Client) MetaCache {
	return &metaCache{
		kubecli: kubecli,
		cache:   sync.Map{},
	}
}

type metaCache struct {
	kubecli client.Client
	cache   sync.Map
}

func (m *metaCache) GetMetaInfo(ctx context.Context, env, tenant, cluster string, nextGen bool, byoc bool) (*MetaInfo, error) {
	v, ok := m.cache.Load(cluster)
	if ok {
		return v.(*MetaInfo), nil
	}
	o11ycluster, err := m.doGetCluster(ctx, env, tenant, cluster, nextGen, byoc)
	if err != nil {
		return nil, err
	}
	if o11ycluster == nil {
		return nil, nil
	}
	info := &MetaInfo{
		VMAccountID: o11ycluster.Spec.VictoriaAccount.AccountID,
		VMProjectID: o11ycluster.Spec.VictoriaAccount.ProjectID,
	}
	m.cache.Store(cluster, info)
	return info, nil
}

func (m *metaCache) doGetCluster(ctx context.Context, env, tenant, cluster string, nextGen bool, byoc bool) (*o11yv1.Cluster, error) {
	clusters := &o11yv1.ClusterList{}
	if err := m.kubecli.List(ctx, clusters, client.InNamespace(getNamespace(env, tenant, nextGen, byoc)), client.MatchingLabels{
		annotationApplicationID: cluster,
	}); err != nil {
		return nil, err
	}
	if len(clusters.Items) != 1 {
		return nil, nil
	}
	return &clusters.Items[0], nil
}

func getNamespace(env, tenant string, nextGen bool, byoc bool) string {
	if byoc {
		return "byoc-" + tenant
	}
	if nextGen {
		return fmt.Sprintf("%s-tidbcloud-nextgen-%s", env, tenant)
	}
	switch env {
	case "prod":
		return "tidbcloud-" + tenant
	case "staging":
		return "staging-tidbcloud-" + tenant
	case "dev":
		fallthrough
	default:
		return "dev-tidbcloud-" + tenant
	}
}
