package task

import (
	"context"
	"strconv"

	k8sent "github.com/tidbcloud/devops/entity/k8supgrade"
	"github.com/tidbcloud/devops/pkg/service/k8supgrade/infrainfo"
)

func (s *svc) enrichTaskClustersTenantContact(ctx context.Context, task *k8sent.Task) {
	cache := map[uint64]*tenantCacheEntry{}
	for _, cluster := range task.K8sClusterList {
		s.enrichClusterTenantContact(ctx, cluster, cache)
	}
}

func (s *svc) enrichClusterTenantContact(ctx context.Context, cluster *k8sent.K8sCluster, cache map[uint64]*tenantCacheEntry) {
	contact := s.resolveClusterTenantContact(ctx, cluster, cache)
	cluster.SalesOwnerEmail = contact.salesOwnerEmail
	cluster.TAMName = contact.tamName
	if contact.tenantName != "" {
		cluster.TenantName = contact.tenantName
	}
}

func (s *svc) resolveClusterTenantContact(ctx context.Context, cluster *k8sent.K8sCluster, cache map[uint64]*tenantCacheEntry) tenantCacheEntry {
	tid, ok := clusterTenantID(cluster)
	if !ok {
		info, err := s.infraInfoSvc.GetK8sInformation(ctx, &infrainfo.GetK8SInformationReq{
			CloudProvider: cluster.CloudProvider,
			Name:          cluster.Name,
			Region:        cluster.Region,
		})
		if err == nil && info != nil {
			tid, ok = parseTenantID(info.TenantID)
		}
	}
	if !ok {
		return tenantCacheEntry{}
	}

	if ce, ok := cache[tid]; ok {
		return *ce
	}

	ten, err := s.tenantSvc.GetTenant(ctx, tid)
	if err != nil || ten == nil {
		return tenantCacheEntry{}
	}

	contact := tenantCacheEntry{
		tenantID:        tid,
		tenantName:      ten.Name,
		salesOwnerEmail: ten.SalesOwnerEmail,
		tamName:         ten.TAMName,
	}
	cache[tid] = &contact
	return contact
}

func clusterTenantID(cluster *k8sent.K8sCluster) (uint64, bool) {
	for _, info := range []*k8sent.K8sInfo{cluster.Info, cluster.K8sSnapshot} {
		if tid, ok := parseTenantID(infoTenantID(info)); ok {
			return tid, true
		}
	}
	return 0, false
}

func infoTenantID(info *k8sent.K8sInfo) string {
	if info == nil {
		return ""
	}
	return info.TenantID
}

func parseTenantID(raw string) (uint64, bool) {
	if raw == "" {
		return 0, false
	}
	tid, err := strconv.ParseUint(raw, 10, 64)
	if err != nil || tid == 0 {
		return 0, false
	}
	return tid, true
}
