package dataservice

import (
	"context"
	"fmt"
	"sync"
	"time"

	"github.com/patrickmn/go-cache"

	"github.com/tidbcloud/observability/pkg/common/configs"
	"github.com/tidbcloud/observability/pkg/common/constants"
	"github.com/tidbcloud/observability/pkg/common/structs"
	"github.com/tidbcloud/observability/pkg/resourcemanager"
)

type HistoricalDataHandler struct {
}

var historicalDataHandler *HistoricalDataHandler

var once sync.Once

const cacheTime = time.Hour * 4

var lock sync.RWMutex
var historicalClusterCache = cache.New(cacheTime, cacheTime*2)

func GetHandler() *HistoricalDataHandler {
	once.Do(func() {
		if historicalDataHandler == nil {
			historicalDataHandler = new(HistoricalDataHandler)
		}
	})

	return historicalDataHandler
}

func (p *HistoricalDataHandler) GetArchivedCluster(ctx context.Context, uniqueKey structs.ClusterUniqueKey) (archived structs.ArchivedClusterInfo, err error) {
	if cluster, ok := historicalClusterCache.Get(uniqueKey.Splice()); ok {
		return cluster.(structs.ArchivedClusterInfo), nil
	}

	lock.Lock()
	defer lock.Unlock()
	if cluster, ok := historicalClusterCache.Get(uniqueKey.Splice()); ok {
		return cluster.(structs.ArchivedClusterInfo), nil
	}

	archived, err = resourcemanager.GetArchivedClusterReaderWriter().Get(ctx, objectStorageResourceName(uniqueKey), uniqueKey)
	if err == nil {
		historicalClusterCache.SetDefault(uniqueKey.Splice(), archived)
	}

	return
}

func objectStorageResourceName(uniqueKey structs.ClusterUniqueKey) string {
	svcInfo := configs.GetServiceInfo()
	if bucket := svcInfo.BizTypeConfigs[uniqueKey.BizType].SpecificBucket; len(bucket) > 0 {
		return bucket
	} else {
		return fmt.Sprintf(constants.StorageBucketNameTemplate, svcInfo.Env, constants.DefaultBucketGroup, configs.GetServiceInfo().LogicalRegionName)
	}
}
